@jxsuite/studio 2.0.0 → 2.0.1
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/chunks/{components-0hzentwq.js → components-799jpvhm.js} +4 -4
- package/dist/chunks/{extension-sections-qct0gt8f.js → extension-sections-qr3drkkw.js} +10 -10
- package/dist/chunks/{files-02zn5y24.js → files-j8a1t06k.js} +8 -8
- package/dist/chunks/{format-host-2c188n41.js → format-host-8jxwts2p.js} +2 -2
- package/dist/chunks/{git-panel-mbb0y0hz.js → git-panel-xtq5z81x.js} +6 -6
- package/dist/chunks/{layers-panel-9qekmqk1.js → layers-panel-ancn2wpq.js} +8 -8
- package/dist/chunks/{settings-modal-gj0hrah4.js → settings-modal-17ttr96g.js} +9 -9
- package/dist/chunks/{studio-asvf0j9e.js → studio-0xgs7xrs.js} +2 -2
- package/dist/chunks/{studio-d77qm3pk.js → studio-4d8hzcz5.js} +8 -8
- package/dist/chunks/{studio-hhj92gcr.js → studio-esrewxap.js} +2 -2
- package/dist/chunks/{studio-97qcgvdn.js → studio-gs6kqdt1.js} +2 -2
- package/dist/chunks/{studio-n9zmpxjg.js → studio-jm0z592w.js} +8 -8
- package/dist/chunks/{studio-j6gqyjf4.js → studio-m2t4mdg5.js} +8 -8
- package/dist/chunks/{studio-wd6ewdvd.js → studio-n4p11dfy.js} +6 -6
- package/dist/chunks/{studio-rq0vxb19.js → studio-sjh1wt1a.js} +2 -2
- package/dist/chunks/{studio-ygzav7z5.js → studio-v7jkjqng.js} +6 -6
- package/dist/chunks/{studio-zmy7241e.js → studio-yfcstdzy.js} +2 -2
- package/dist/chunks/{studio-568nx4t5.js → studio-zp7jncs8.js} +6 -6
- package/dist/chunks/{studio-568nx4t5.js.map → studio-zp7jncs8.js.map} +1 -1
- package/dist/studio.js +113 -82
- package/package.json +1 -1
- package/src/new-project/import-tab.ts +27 -9
- package/src/new-project/new-project-modal.ts +49 -17
- package/src/panels/ai-panel.ts +9 -76
- package/src/services/ai-models.ts +45 -1
- package/src/ui/ai-managed-connect.ts +107 -0
- /package/dist/chunks/{components-0hzentwq.js.map → components-799jpvhm.js.map} +0 -0
- /package/dist/chunks/{extension-sections-qct0gt8f.js.map → extension-sections-qr3drkkw.js.map} +0 -0
- /package/dist/chunks/{files-02zn5y24.js.map → files-j8a1t06k.js.map} +0 -0
- /package/dist/chunks/{format-host-2c188n41.js.map → format-host-8jxwts2p.js.map} +0 -0
- /package/dist/chunks/{git-panel-mbb0y0hz.js.map → git-panel-xtq5z81x.js.map} +0 -0
- /package/dist/chunks/{layers-panel-9qekmqk1.js.map → layers-panel-ancn2wpq.js.map} +0 -0
- /package/dist/chunks/{settings-modal-gj0hrah4.js.map → settings-modal-17ttr96g.js.map} +0 -0
- /package/dist/chunks/{studio-asvf0j9e.js.map → studio-0xgs7xrs.js.map} +0 -0
- /package/dist/chunks/{studio-d77qm3pk.js.map → studio-4d8hzcz5.js.map} +0 -0
- /package/dist/chunks/{studio-hhj92gcr.js.map → studio-esrewxap.js.map} +0 -0
- /package/dist/chunks/{studio-97qcgvdn.js.map → studio-gs6kqdt1.js.map} +0 -0
- /package/dist/chunks/{studio-n9zmpxjg.js.map → studio-jm0z592w.js.map} +0 -0
- /package/dist/chunks/{studio-j6gqyjf4.js.map → studio-m2t4mdg5.js.map} +0 -0
- /package/dist/chunks/{studio-wd6ewdvd.js.map → studio-n4p11dfy.js.map} +0 -0
- /package/dist/chunks/{studio-rq0vxb19.js.map → studio-sjh1wt1a.js.map} +0 -0
- /package/dist/chunks/{studio-ygzav7z5.js.map → studio-v7jkjqng.js.map} +0 -0
- /package/dist/chunks/{studio-zmy7241e.js.map → studio-yfcstdzy.js.map} +0 -0
|
@@ -9,6 +9,6 @@
|
|
|
9
9
|
"/// <reference lib=\"dom\" />\n/**\n * Pull orchestration that keeps project sync from being blocked by Studio's own automated package\n * updates. The on-open @jxsuite update rewrites package.json and bun.lock without committing, so a\n * teammate pushing the same update makes a later `git pull` refuse to merge. Since those local\n * changes are machine-generated and reproducible, we discard them, pull, and re-run the package\n * sync (re-apply the update if the pulled project is still behind, or `bun install` if the pull\n * brought it). Detection is state-based (git status + content comparison against `@{u}`), never git\n * stderr parsing, so it works identically across backends and locales.\n */\n\nimport { errorMessage } from \"@jxsuite/schema/parse\";\nimport { getPlatform } from \"../platform\";\nimport { showConfirmDialog } from \"../ui/layers\";\nimport { showProgressModal } from \"../ui/progress-modal\";\nimport { statusMessage } from \"../panels/statusbar\";\nimport { applyJxsuiteUpdate, checkJxsuiteUpdate } from \"./jxsuite-update\";\nimport type { GitStatusResult } from \"../types\";\n\nconst PKG_PATHS = [\"package.json\", \"bun.lock\", \"bun.lockb\"];\n\n/** Untracked markers across backends: desktop porcelain v1 emits \"??\", server porcelain v2 \"U\". */\nconst UNTRACKED_STATUSES = new Set([\"??\", \"U\"]);\n\n/** Above this many dirty files, skip the per-file upstream comparison and leave the error as-is. */\nconst MAX_CONFLICT_SCAN = 25;\n\nconst JXSUITE_PREFIX = \"@jxsuite/\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction sortKeys(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map((entry) => sortKeys(entry));\n }\n if (isRecord(value)) {\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(value).toSorted()) {\n out[key] = sortKeys(value[key]);\n }\n return out;\n }\n return value;\n}\n\n/** Replace every @jxsuite/* version in dependencies/devDependencies so they compare equal. */\nfunction maskJxsuiteVersions(pkg: Record<string, unknown>): Record<string, unknown> {\n const out = { ...pkg };\n for (const section of [\"dependencies\", \"devDependencies\"]) {\n const deps = out[section];\n if (!isRecord(deps)) {\n continue;\n }\n const masked = { ...deps };\n for (const name of Object.keys(masked)) {\n if (name.startsWith(JXSUITE_PREFIX)) {\n masked[name] = \"*\";\n }\n }\n out[section] = masked;\n }\n return out;\n}\n\n/**\n * True when the working package.json differs from the HEAD copy only in the version strings of\n * jxsuite-scoped entries — i.e. exactly what Studio's automated update writes. Added/removed deps\n * or any other edit means a human touched the file.\n */\nexport function isAutomatedPackageDiff(\n headText: string | null,\n workingText: string | null,\n): boolean {\n if (headText === null || workingText === null) {\n return false;\n }\n let head: unknown;\n let working: unknown;\n try {\n head = JSON.parse(headText);\n working = JSON.parse(workingText);\n } catch {\n return false;\n }\n if (!isRecord(head) || !isRecord(working)) {\n return false;\n }\n return (\n JSON.stringify(sortKeys(maskJxsuiteVersions(head))) ===\n JSON.stringify(sortKeys(maskJxsuiteVersions(working)))\n );\n}\n\nasync function tryShow(path: string, ref: string): Promise<string | null> {\n try {\n return await getPlatform().gitShow({ path, ref });\n } catch {\n return null;\n }\n}\n\nasync function tryRead(path: string): Promise<string | null> {\n try {\n return await getPlatform().readFile(path);\n } catch {\n return null;\n }\n}\n\nexport interface PackagePullPlan {\n /** Tracked dirty package files whose upstream (@{u}) content differs from HEAD. */\n discard: string[];\n /** Untracked package files that exist at @{u} (\"untracked would be overwritten\" case). */\n removeUntracked: string[];\n /** Whether the package.json working copy diverges from HEAD only by automated @jxsuite bumps. */\n automated: boolean;\n}\n\n/**\n * Decide which local package files stand in the way of a merge. Only files the upstream actually\n * changed can block the pull, so files whose @{u} content matches HEAD are left alone.\n */\nexport async function planPackageDiscard(status: GitStatusResult): Promise<PackagePullPlan> {\n const discard: string[] = [];\n const removeUntracked: string[] = [];\n let automated = true;\n for (const path of PKG_PATHS) {\n const entries = status.files.filter((f) => f.path === path);\n if (entries.length === 0) {\n continue;\n }\n const upstream = await tryShow(path, \"@{u}\");\n if (entries.every((f) => UNTRACKED_STATUSES.has(f.status))) {\n if (upstream !== null) {\n removeUntracked.push(path);\n }\n continue;\n }\n const head = await tryShow(path, \"HEAD\");\n if (upstream === null || upstream === head) {\n continue;\n }\n discard.push(path);\n if (path === \"package.json\") {\n automated &&= isAutomatedPackageDiff(head, await tryRead(path));\n }\n }\n return { automated, discard, removeUntracked };\n}\n\nfunction planIsEmpty(plan: PackagePullPlan): boolean {\n return plan.discard.length === 0 && plan.removeUntracked.length === 0;\n}\n\n/** True when a dirty non-package file also differs upstream — recovery can't unblock that pull. */\nasync function otherFilesConflict(status: GitStatusResult): Promise<boolean> {\n const paths = [\n ...new Set(status.files.filter((f) => !PKG_PATHS.includes(f.path)).map((f) => f.path)),\n ];\n if (paths.length > MAX_CONFLICT_SCAN) {\n return true;\n }\n for (const path of paths) {\n const upstream = await tryShow(path, \"@{u}\");\n if (upstream !== null && upstream !== (await tryShow(path, \"HEAD\"))) {\n return true;\n }\n }\n return false;\n}\n\nasync function applyDiscard(plan: PackagePullPlan): Promise<void> {\n const platform = getPlatform();\n if (plan.discard.length > 0) {\n // Unstage unconditionally: desktop porcelain v1 doesn't report a staged flag.\n // Restoring an unstaged tracked file is a no-op.\n await platform.gitUnstage(plan.discard);\n await platform.gitDiscard(plan.discard);\n }\n for (const path of plan.removeUntracked) {\n await platform.deleteFile(path);\n }\n}\n\n/**\n * Bring packages back in line after a pull that touched (or followed a discard of) package files:\n * re-apply the @jxsuite update if the pulled project is still behind, otherwise `bun install` so\n * node_modules matches the pulled lockfile. Never throws — a successful pull must not turn into an\n * error banner; failures surface through the progress modal.\n */\nasync function syncPackagesAfterPull(): Promise<void> {\n const platform = getPlatform();\n let check: Awaited<ReturnType<typeof checkJxsuiteUpdate>> = null;\n try {\n check = await checkJxsuiteUpdate();\n } catch {\n check = null;\n }\n if (check && platform.setPackageVersions) {\n // No re-prompt: the discarded local changes came from an update the user already accepted.\n await applyJxsuiteUpdate(check.outdated, check.target);\n return;\n }\n if (!platform.installDependencies) {\n return;\n }\n const progress = showProgressModal({\n status: \"Running bun install…\",\n title: \"Syncing dependencies\",\n });\n try {\n const result = await platform.installDependencies();\n if (result.ok) {\n progress.done();\n } else {\n progress.fail(result.log ?? \"bun install failed\");\n }\n } catch (error) {\n progress.fail(errorMessage(error));\n }\n}\n\n/**\n * Discard per plan, pull, and re-sync. A discard is always followed by a package re-sync — even\n * when the pull fails — so the project is never stranded without the update it had before.\n */\nasync function discardPullAndSync(plan: PackagePullPlan): Promise<void> {\n const platform = getPlatform();\n try {\n await applyDiscard(plan);\n } catch (error) {\n throw new Error(`Could not reset local package files: ${errorMessage(error)}`, {\n cause: error,\n });\n }\n try {\n await platform.gitPull();\n } catch (error) {\n await syncPackagesAfterPull();\n throw error;\n }\n statusMessage(\"Local package updates were superseded by pulled changes\");\n await syncPackagesAfterPull();\n}\n\nasync function recoverAfterFailedPull(original: unknown): Promise<void> {\n const platform = getPlatform();\n let status: GitStatusResult;\n try {\n status = await platform.gitStatus();\n } catch {\n throw original;\n }\n if (!(status.behind > 0)) {\n throw original;\n }\n const plan = await planPackageDiscard(status);\n if (planIsEmpty(plan) || (await otherFilesConflict(status))) {\n throw original;\n }\n if (!plan.automated) {\n const confirmed = await showConfirmDialog(\n \"Discard local package changes?\",\n \"package.json / bun.lock have local edits that conflict with incoming changes. Discard them, pull, and re-sync packages?\",\n { confirmLabel: \"Discard and pull\", destructive: true },\n );\n if (!confirmed) {\n throw original;\n }\n }\n await discardPullAndSync(plan);\n}\n\n/**\n * Snapshot the package files (aligned to PKG_PATHS). Lists the root once and reads only the files\n * that exist, so absent lockfiles (cloud projects don't commit one) never trigger a console 404\n * from a blind read. Listing failure falls back to probing all paths.\n */\n/**\n * Snapshot the package files (aligned to PKG_PATHS). Lists the root once and reads only the files\n * that exist, so absent lockfiles (cloud projects don't commit one) never trigger a console 404\n * from a blind read. Listing failure falls back to probing all paths.\n */\nasync function snapshotPackageFiles(): Promise<(string | null)[]> {\n let present: Set<string>;\n try {\n const entries = await getPlatform().listDirectory(\"\");\n present = new Set(entries.filter((e) => e.type === \"file\").map((e) => e.name));\n } catch {\n present = new Set(PKG_PATHS);\n }\n return Promise.all(\n PKG_PATHS.map((path) => (present.has(path) ? tryRead(path) : Promise.resolve(null))),\n );\n}\n\n/**\n * Pull with automatic recovery from conflicts caused by Studio's own package updates. Throws only\n * when the pull genuinely fails for reasons recovery can't (or shouldn't) fix.\n */\nexport async function pullWithPackageSync(): Promise<void> {\n const platform = getPlatform();\n const before = await snapshotPackageFiles();\n\n // Preemptive: fetch so `behind` is current, then reset automated package edits that would\n // Block the merge — manual package.json edits fall through to the plain pull + confirm path.\n let status: GitStatusResult | null = null;\n try {\n await platform.gitFetch();\n status = await platform.gitStatus();\n } catch {\n status = null; // Offline or status failure — the plain pull will report the real error\n }\n if (status && status.behind > 0) {\n const plan = await planPackageDiscard(status);\n if (!planIsEmpty(plan) && plan.automated) {\n await discardPullAndSync(plan);\n return;\n }\n }\n\n try {\n await platform.gitPull();\n } catch (error) {\n await recoverAfterFailedPull(error);\n return;\n }\n const after = await snapshotPackageFiles();\n if (before.some((content, i) => content !== after[i])) {\n await syncPackagesAfterPull();\n }\n}\n\n/**\n * Pull remote changes as soon as a project opens, ahead of the install check and update prompt, so\n * a session starts from the current remote state. Never throws and never blocks the open — failures\n * (offline, no upstream, unrelated conflicts) surface as a status message only.\n */\nexport async function autoSyncProjectOnOpen(): Promise<void> {\n const platform = getPlatform();\n let status: GitStatusResult;\n try {\n status = await platform.gitStatus();\n } catch {\n return;\n }\n if (!status?.isRepo || (status.remotes?.length ?? 0) === 0) {\n return;\n }\n statusMessage(\"Syncing project…\");\n try {\n await pullWithPackageSync();\n } catch (error) {\n statusMessage(`Sync skipped: ${errorMessage(error)}`);\n }\n}\n"
|
|
10
10
|
],
|
|
11
11
|
"mappings": "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",
|
|
12
|
-
"debugId": "
|
|
12
|
+
"debugId": "88C48B6EB01A9FE764756E2164756E21",
|
|
13
13
|
"names": []
|
|
14
14
|
}
|
package/dist/studio.js
CHANGED
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
stringify1 as stringify2,
|
|
52
52
|
stringifyPosition,
|
|
53
53
|
whitespace
|
|
54
|
-
} from "./chunks/studio-
|
|
54
|
+
} from "./chunks/studio-jm0z592w.js";
|
|
55
55
|
import {
|
|
56
56
|
getCfToken,
|
|
57
57
|
hydrateSettings,
|
|
@@ -109,7 +109,7 @@ import {
|
|
|
109
109
|
import {
|
|
110
110
|
registerFormControl,
|
|
111
111
|
renderFieldRow
|
|
112
|
-
} from "./chunks/studio-
|
|
112
|
+
} from "./chunks/studio-yfcstdzy.js";
|
|
113
113
|
import {
|
|
114
114
|
addFieldFormTpl,
|
|
115
115
|
detectFieldFormat,
|
|
@@ -122,7 +122,7 @@ import {
|
|
|
122
122
|
schemaForType,
|
|
123
123
|
schemeOfQuery,
|
|
124
124
|
yamlDefault
|
|
125
|
-
} from "./chunks/studio-
|
|
125
|
+
} from "./chunks/studio-m2t4mdg5.js";
|
|
126
126
|
import {
|
|
127
127
|
ROW_KEY_FIELD,
|
|
128
128
|
addRecentProject,
|
|
@@ -162,7 +162,7 @@ import {
|
|
|
162
162
|
setupTreeKeyboard,
|
|
163
163
|
startFsSync,
|
|
164
164
|
trackRecentFile
|
|
165
|
-
} from "./chunks/studio-
|
|
165
|
+
} from "./chunks/studio-4d8hzcz5.js";
|
|
166
166
|
import {
|
|
167
167
|
MEDIA_EXTENSIONS,
|
|
168
168
|
UPLOAD_ACCEPT,
|
|
@@ -245,13 +245,13 @@ import {
|
|
|
245
245
|
updateActivePanelHeaders,
|
|
246
246
|
updateSiteConfig,
|
|
247
247
|
uploadAssets
|
|
248
|
-
} from "./chunks/studio-
|
|
248
|
+
} from "./chunks/studio-v7jkjqng.js";
|
|
249
249
|
import {
|
|
250
250
|
buildComponentInstance,
|
|
251
251
|
componentRegistry,
|
|
252
252
|
computeRelativePath,
|
|
253
253
|
loadComponentRegistry
|
|
254
|
-
} from "./chunks/studio-
|
|
254
|
+
} from "./chunks/studio-esrewxap.js";
|
|
255
255
|
import {
|
|
256
256
|
classMap,
|
|
257
257
|
ifDefined,
|
|
@@ -262,7 +262,7 @@ import {
|
|
|
262
262
|
platformSupportsClone,
|
|
263
263
|
refreshGitStatus,
|
|
264
264
|
renderGitPanel
|
|
265
|
-
} from "./chunks/studio-
|
|
265
|
+
} from "./chunks/studio-n4p11dfy.js";
|
|
266
266
|
import {
|
|
267
267
|
repeat
|
|
268
268
|
} from "./chunks/studio-xq0t7n5t.js";
|
|
@@ -277,7 +277,7 @@ import {
|
|
|
277
277
|
VERSION,
|
|
278
278
|
autoSyncProjectOnOpen,
|
|
279
279
|
maybePromptJxsuiteUpdate
|
|
280
|
-
} from "./chunks/studio-
|
|
280
|
+
} from "./chunks/studio-zp7jncs8.js";
|
|
281
281
|
import {
|
|
282
282
|
applyPanelCollapse,
|
|
283
283
|
errorMessage,
|
|
@@ -295,7 +295,7 @@ import {
|
|
|
295
295
|
showSaveDiscardDialog,
|
|
296
296
|
statusMessage,
|
|
297
297
|
view
|
|
298
|
-
} from "./chunks/studio-
|
|
298
|
+
} from "./chunks/studio-0xgs7xrs.js";
|
|
299
299
|
import {
|
|
300
300
|
COMMON_SELECTORS,
|
|
301
301
|
VOID_ELEMENTS,
|
|
@@ -392,7 +392,7 @@ import {
|
|
|
392
392
|
updateUi,
|
|
393
393
|
varDisplayName,
|
|
394
394
|
workspace
|
|
395
|
-
} from "./chunks/studio-
|
|
395
|
+
} from "./chunks/studio-sjh1wt1a.js";
|
|
396
396
|
import {
|
|
397
397
|
AsyncDirective,
|
|
398
398
|
PartType,
|
|
@@ -416,7 +416,7 @@ import {
|
|
|
416
416
|
loadedMonaco,
|
|
417
417
|
refreshExtensionUi,
|
|
418
418
|
refreshFormats
|
|
419
|
-
} from "./chunks/studio-
|
|
419
|
+
} from "./chunks/studio-gs6kqdt1.js";
|
|
420
420
|
import {
|
|
421
421
|
getPlatform,
|
|
422
422
|
hasPlatform,
|
|
@@ -19573,7 +19573,7 @@ function renderSiteLevelImports(renderLeftPanel) {
|
|
|
19573
19573
|
const platform = getPlatform();
|
|
19574
19574
|
await platform.removePackage(pkg);
|
|
19575
19575
|
const updatedElements = siteElements.filter((e) => typeof e !== "string" || !e.startsWith(`${pkg}/`));
|
|
19576
|
-
const { loadComponentRegistry: loadComponentRegistry2 } = await import("./chunks/components-
|
|
19576
|
+
const { loadComponentRegistry: loadComponentRegistry2 } = await import("./chunks/components-799jpvhm.js");
|
|
19577
19577
|
await loadComponentRegistry2();
|
|
19578
19578
|
await updateSiteConfig({
|
|
19579
19579
|
$elements: updatedElements
|
|
@@ -19643,7 +19643,7 @@ function renderSiteLevelImports(renderLeftPanel) {
|
|
|
19643
19643
|
try {
|
|
19644
19644
|
const platform = getPlatform();
|
|
19645
19645
|
await platform.addPackage(name);
|
|
19646
|
-
const { loadComponentRegistry: loadComponentRegistry2 } = await import("./chunks/components-
|
|
19646
|
+
const { loadComponentRegistry: loadComponentRegistry2 } = await import("./chunks/components-799jpvhm.js");
|
|
19647
19647
|
await loadComponentRegistry2();
|
|
19648
19648
|
renderLeftPanel();
|
|
19649
19649
|
} catch (error) {
|
|
@@ -19665,7 +19665,7 @@ function renderSiteLevelImports(renderLeftPanel) {
|
|
|
19665
19665
|
try {
|
|
19666
19666
|
const platform = getPlatform();
|
|
19667
19667
|
await platform.addPackage(name);
|
|
19668
|
-
const { loadComponentRegistry: loadComponentRegistry2 } = await import("./chunks/components-
|
|
19668
|
+
const { loadComponentRegistry: loadComponentRegistry2 } = await import("./chunks/components-799jpvhm.js");
|
|
19669
19669
|
await loadComponentRegistry2();
|
|
19670
19670
|
renderLeftPanel();
|
|
19671
19671
|
} catch (error) {
|
|
@@ -23908,11 +23908,27 @@ var cache2 = null;
|
|
|
23908
23908
|
var proxyConfigured = false;
|
|
23909
23909
|
var proxyManaged = false;
|
|
23910
23910
|
var proxyDefaultModel = "";
|
|
23911
|
+
var proxyProbe = null;
|
|
23912
|
+
var probeListeners = new Set;
|
|
23911
23913
|
function invalidateModelCache() {
|
|
23912
23914
|
cache2 = null;
|
|
23913
23915
|
proxyConfigured = false;
|
|
23914
23916
|
proxyManaged = false;
|
|
23915
23917
|
proxyDefaultModel = "";
|
|
23918
|
+
proxyProbe = null;
|
|
23919
|
+
}
|
|
23920
|
+
function ensureProxyProbe(onSettled) {
|
|
23921
|
+
if (onSettled) {
|
|
23922
|
+
probeListeners.add(onSettled);
|
|
23923
|
+
}
|
|
23924
|
+
proxyProbe ??= fetchAvailableModels({ force: true }).catch(() => {}).then(() => {
|
|
23925
|
+
for (const notify of probeListeners) {
|
|
23926
|
+
notify();
|
|
23927
|
+
}
|
|
23928
|
+
});
|
|
23929
|
+
}
|
|
23930
|
+
function hasAiCredentials() {
|
|
23931
|
+
return hasOpenAiKey() || isProxyConfigured();
|
|
23916
23932
|
}
|
|
23917
23933
|
function isProxyConfigured() {
|
|
23918
23934
|
return proxyConfigured;
|
|
@@ -24074,6 +24090,54 @@ function createAiCredentialsForm(opts) {
|
|
|
24074
24090
|
}
|
|
24075
24091
|
return { render: render5, startEdit };
|
|
24076
24092
|
}
|
|
24093
|
+
|
|
24094
|
+
// src/ui/ai-managed-connect.ts
|
|
24095
|
+
function createManagedConnect(opts) {
|
|
24096
|
+
let busy = false;
|
|
24097
|
+
let connectError = "";
|
|
24098
|
+
function canOffer() {
|
|
24099
|
+
return isManagedProxy() && !isProxyConfigured() && hasPlatform() && Boolean(getPlatform().cfConnect);
|
|
24100
|
+
}
|
|
24101
|
+
function ensureProbe() {
|
|
24102
|
+
ensureProxyProbe(opts.requestRender);
|
|
24103
|
+
}
|
|
24104
|
+
async function connect() {
|
|
24105
|
+
if (busy) {
|
|
24106
|
+
return;
|
|
24107
|
+
}
|
|
24108
|
+
busy = true;
|
|
24109
|
+
connectError = "";
|
|
24110
|
+
opts.requestRender();
|
|
24111
|
+
try {
|
|
24112
|
+
const connection = await getPlatform().cfConnect?.();
|
|
24113
|
+
if (connection) {
|
|
24114
|
+
await fetchAvailableModels({ force: true });
|
|
24115
|
+
} else {
|
|
24116
|
+
connectError = "Cloudflare connection was not completed.";
|
|
24117
|
+
}
|
|
24118
|
+
} catch (error) {
|
|
24119
|
+
connectError = error instanceof Error ? error.message : String(error);
|
|
24120
|
+
}
|
|
24121
|
+
busy = false;
|
|
24122
|
+
opts.requestRender();
|
|
24123
|
+
}
|
|
24124
|
+
function render5() {
|
|
24125
|
+
if (!canOffer()) {
|
|
24126
|
+
return nothing;
|
|
24127
|
+
}
|
|
24128
|
+
return html`
|
|
24129
|
+
<div class="ai-managed-connect">
|
|
24130
|
+
<div>Use Workers AI on your own Cloudflare account — no API key needed.</div>
|
|
24131
|
+
<sp-button size="s" ?disabled=${busy} @click=${() => void connect()}>
|
|
24132
|
+
${busy ? "Connecting…" : "Connect Cloudflare"}
|
|
24133
|
+
</sp-button>
|
|
24134
|
+
${connectError ? html`<div class="ai-managed-connect-error">${connectError}</div>` : nothing}
|
|
24135
|
+
<div class="ai-managed-connect-divider">— or bring your own key —</div>
|
|
24136
|
+
</div>
|
|
24137
|
+
`;
|
|
24138
|
+
}
|
|
24139
|
+
return { canOffer, ensureProbe, render: render5 };
|
|
24140
|
+
}
|
|
24077
24141
|
// ../../node_modules/@ungap/structured-clone/esm/types.js
|
|
24078
24142
|
var VOID = -1;
|
|
24079
24143
|
var PRIMITIVE = 0;
|
|
@@ -36471,12 +36535,6 @@ function renderSessionsList(opts) {
|
|
|
36471
36535
|
// src/panels/ai-panel.ts
|
|
36472
36536
|
var mounted = false;
|
|
36473
36537
|
var keyEditing = false;
|
|
36474
|
-
var proxyProbe = null;
|
|
36475
|
-
function ensureProxyProbe() {
|
|
36476
|
-
proxyProbe ??= fetchAvailableModels({ force: true }).catch(() => {}).then(() => {
|
|
36477
|
-
scheduleAiRender();
|
|
36478
|
-
});
|
|
36479
|
-
}
|
|
36480
36538
|
var view2 = "chat";
|
|
36481
36539
|
var assistant = createDocumentAssistant();
|
|
36482
36540
|
globalThis.assistant = assistant;
|
|
@@ -36551,49 +36609,11 @@ function startEditApiKey() {
|
|
|
36551
36609
|
keyEditing = true;
|
|
36552
36610
|
credsForm.startEdit();
|
|
36553
36611
|
}
|
|
36554
|
-
var
|
|
36555
|
-
var cfConnectError = "";
|
|
36556
|
-
function canOfferManagedConnect() {
|
|
36557
|
-
return isManagedProxy() && !isProxyConfigured() && Boolean(getPlatform().cfConnect);
|
|
36558
|
-
}
|
|
36559
|
-
async function connectCloudflareForAi() {
|
|
36560
|
-
if (cfConnectBusy) {
|
|
36561
|
-
return;
|
|
36562
|
-
}
|
|
36563
|
-
cfConnectBusy = true;
|
|
36564
|
-
cfConnectError = "";
|
|
36565
|
-
scheduleAiRender();
|
|
36566
|
-
try {
|
|
36567
|
-
const connection = await getPlatform().cfConnect?.();
|
|
36568
|
-
if (connection) {
|
|
36569
|
-
await fetchAvailableModels({ force: true });
|
|
36570
|
-
} else {
|
|
36571
|
-
cfConnectError = "Cloudflare connection was not completed.";
|
|
36572
|
-
}
|
|
36573
|
-
} catch (error) {
|
|
36574
|
-
cfConnectError = error instanceof Error ? error.message : String(error);
|
|
36575
|
-
}
|
|
36576
|
-
cfConnectBusy = false;
|
|
36577
|
-
scheduleAiRender();
|
|
36578
|
-
}
|
|
36579
|
-
function renderManagedConnect() {
|
|
36580
|
-
return html`
|
|
36581
|
-
<div class="ai-managed-connect">
|
|
36582
|
-
<div>Use Workers AI on your own Cloudflare account — no API key needed.</div>
|
|
36583
|
-
<sp-button size="s" ?disabled=${cfConnectBusy} @click=${() => void connectCloudflareForAi()}>
|
|
36584
|
-
${cfConnectBusy ? "Connecting…" : "Connect Cloudflare"}
|
|
36585
|
-
</sp-button>
|
|
36586
|
-
${cfConnectError ? html`<div class="ai-managed-connect-error">${cfConnectError}</div>` : nothing}
|
|
36587
|
-
<div class="ai-managed-connect-divider">— or bring your own key —</div>
|
|
36588
|
-
</div>
|
|
36589
|
-
`;
|
|
36590
|
-
}
|
|
36612
|
+
var managedConnect = createManagedConnect({ requestRender: scheduleAiRender });
|
|
36591
36613
|
function renderKeyGate() {
|
|
36592
36614
|
return html`
|
|
36593
36615
|
<div class="ai-tab-body">
|
|
36594
|
-
<div class="ai-status-center">
|
|
36595
|
-
${canOfferManagedConnect() ? renderManagedConnect() : nothing} ${credsForm.render()}
|
|
36596
|
-
</div>
|
|
36616
|
+
<div class="ai-status-center">${managedConnect.render()} ${credsForm.render()}</div>
|
|
36597
36617
|
</div>
|
|
36598
36618
|
`;
|
|
36599
36619
|
}
|
|
@@ -36678,9 +36698,9 @@ var composer = createComposer({
|
|
|
36678
36698
|
requestRender: scheduleAiRender
|
|
36679
36699
|
});
|
|
36680
36700
|
function renderAiPanelTemplate() {
|
|
36681
|
-
if (!
|
|
36701
|
+
if (!hasAiCredentials() || keyEditing) {
|
|
36682
36702
|
if (!keyEditing) {
|
|
36683
|
-
|
|
36703
|
+
managedConnect.ensureProbe();
|
|
36684
36704
|
}
|
|
36685
36705
|
return renderKeyGate();
|
|
36686
36706
|
}
|
|
@@ -65568,13 +65588,13 @@ function renderImportStatus() {
|
|
|
65568
65588
|
`;
|
|
65569
65589
|
}
|
|
65570
65590
|
function renderImportSource(ctx) {
|
|
65571
|
-
if (!
|
|
65591
|
+
if (!ctx.aiGateOpen()) {
|
|
65572
65592
|
return html`
|
|
65573
65593
|
<div class="new-project-tab-intro">
|
|
65574
|
-
Importing uses an AI-guided pipeline to clone an existing site.
|
|
65575
|
-
key to continue.
|
|
65594
|
+
Importing uses an AI-guided pipeline to clone an existing site.
|
|
65595
|
+
${ctx.managedConnect.canOffer() ? "Connect Cloudflare, or add an OpenAI-compatible API key, to continue." : "Add an OpenAI-compatible API key to continue."}
|
|
65576
65596
|
</div>
|
|
65577
|
-
<div class="new-project-creds">${ctx.credsForm.render()}</div>
|
|
65597
|
+
<div class="new-project-creds">${ctx.managedConnect.render()} ${ctx.credsForm.render()}</div>
|
|
65578
65598
|
`;
|
|
65579
65599
|
}
|
|
65580
65600
|
return html`
|
|
@@ -65669,21 +65689,30 @@ var _creating = false;
|
|
|
65669
65689
|
var _starters = [];
|
|
65670
65690
|
var _resolve2 = null;
|
|
65671
65691
|
var _credsForm = null;
|
|
65692
|
+
function rerenderIfOpen() {
|
|
65693
|
+
if (_handle5) {
|
|
65694
|
+
renderModal3();
|
|
65695
|
+
}
|
|
65696
|
+
}
|
|
65672
65697
|
function credsForm2() {
|
|
65673
65698
|
_credsForm ??= createAiCredentialsForm({
|
|
65674
|
-
onSaved:
|
|
65675
|
-
|
|
65676
|
-
renderModal3();
|
|
65677
|
-
}
|
|
65678
|
-
},
|
|
65679
|
-
requestRender: () => {
|
|
65680
|
-
if (_handle5) {
|
|
65681
|
-
renderModal3();
|
|
65682
|
-
}
|
|
65683
|
-
}
|
|
65699
|
+
onSaved: rerenderIfOpen,
|
|
65700
|
+
requestRender: rerenderIfOpen
|
|
65684
65701
|
});
|
|
65685
65702
|
return _credsForm;
|
|
65686
65703
|
}
|
|
65704
|
+
var _managedConnect = null;
|
|
65705
|
+
function managedConnect2() {
|
|
65706
|
+
_managedConnect ??= createManagedConnect({ requestRender: rerenderIfOpen });
|
|
65707
|
+
return _managedConnect;
|
|
65708
|
+
}
|
|
65709
|
+
function aiGateOpen() {
|
|
65710
|
+
if (hasAiCredentials()) {
|
|
65711
|
+
return true;
|
|
65712
|
+
}
|
|
65713
|
+
managedConnect2().ensureProbe();
|
|
65714
|
+
return false;
|
|
65715
|
+
}
|
|
65687
65716
|
function openNewProjectModal(options) {
|
|
65688
65717
|
if (_handle5) {
|
|
65689
65718
|
return Promise.resolve(null);
|
|
@@ -65776,8 +65805,10 @@ function sourceLabel() {
|
|
|
65776
65805
|
function renderModal3() {
|
|
65777
65806
|
const platform = getPlatform();
|
|
65778
65807
|
const importCtx = {
|
|
65808
|
+
aiGateOpen,
|
|
65779
65809
|
credsForm: credsForm2(),
|
|
65780
65810
|
form: _form2,
|
|
65811
|
+
managedConnect: managedConnect2(),
|
|
65781
65812
|
onDone: finish2,
|
|
65782
65813
|
rerender: renderModal3,
|
|
65783
65814
|
resolveDestination: () => validateParams()
|
|
@@ -65968,13 +65999,13 @@ function renderModal3() {
|
|
|
65968
65999
|
</div>
|
|
65969
66000
|
` : html`<div class="new-project-tab-intro">No starter sites are available.</div>`;
|
|
65970
66001
|
const agentSourceTpl = () => {
|
|
65971
|
-
if (!
|
|
66002
|
+
if (!aiGateOpen()) {
|
|
65972
66003
|
return html`
|
|
65973
66004
|
<div class="new-project-tab-intro">
|
|
65974
|
-
The agent uses your AI provider to build the site.
|
|
65975
|
-
continue.
|
|
66005
|
+
The agent uses your AI provider to build the site.
|
|
66006
|
+
${managedConnect2().canOffer() ? "Connect Cloudflare, or add an OpenAI-compatible API key, to continue." : "Add an OpenAI-compatible API key to continue."}
|
|
65976
66007
|
</div>
|
|
65977
|
-
<div class="new-project-creds">${credsForm2().render()}</div>
|
|
66008
|
+
<div class="new-project-creds">${managedConnect2().render()} ${credsForm2().render()}</div>
|
|
65978
66009
|
`;
|
|
65979
66010
|
}
|
|
65980
66011
|
return html`
|
|
@@ -66080,7 +66111,7 @@ function renderModal3() {
|
|
|
66080
66111
|
`;
|
|
66081
66112
|
}
|
|
66082
66113
|
if (_step === "source") {
|
|
66083
|
-
const gated = (_tab === "import" || _tab === "agent") && !
|
|
66114
|
+
const gated = (_tab === "import" || _tab === "agent") && !aiGateOpen();
|
|
66084
66115
|
return html`
|
|
66085
66116
|
<sp-button variant="secondary" @click=${closeNewProjectModal}>Cancel</sp-button>
|
|
66086
66117
|
${gated ? "" : html`<sp-button variant="accent" @click=${goNext}>Next</sp-button>`}
|
|
@@ -73138,5 +73169,5 @@ export {
|
|
|
73138
73169
|
hasUnsavedTabs
|
|
73139
73170
|
};
|
|
73140
73171
|
|
|
73141
|
-
//# debugId=
|
|
73172
|
+
//# debugId=ADA5809F71C01E1464756E2164756E21
|
|
73142
73173
|
//# sourceMappingURL=studio.js.map
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The New Project modal's Import source step: an AI-guided clone of an existing site. Gated behind
|
|
3
|
-
* the AI credentials form
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* the AI credentials gate (key form + the keyless Cloudflare option) until AI is usable — a local
|
|
4
|
+
* key, or a backend holding its own; otherwise a URL + crawl-options form. The name/directory
|
|
5
|
+
* parameters live on the modal's shared Parameters step; the running pipeline streams its progress
|
|
6
|
+
* into a log here and resolves the modal with the imported project.
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
import { html } from "lit-html";
|
|
9
10
|
import { getPlatform } from "../platform";
|
|
10
|
-
import { getBaseUrl, getModel, getOpenAiKey
|
|
11
|
+
import { getBaseUrl, getModel, getOpenAiKey } from "../services/ai-settings";
|
|
11
12
|
import { errorMessage } from "@jxsuite/schema/parse";
|
|
12
13
|
import { destinationPath } from "./location-fields";
|
|
13
14
|
import type { TemplateResult } from "lit-html";
|
|
@@ -20,6 +21,12 @@ export interface CredsFormLike {
|
|
|
20
21
|
startEdit: () => void;
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
/** Structural view of src/ui/ai-managed-connect's controller (the keyless option beside the form). */
|
|
25
|
+
export interface ManagedConnectLike {
|
|
26
|
+
canOffer: () => boolean;
|
|
27
|
+
render: () => unknown;
|
|
28
|
+
}
|
|
29
|
+
|
|
23
30
|
export interface ImportTabCtx {
|
|
24
31
|
/** The modal's shared name/directory state (the import destination slug). */
|
|
25
32
|
form: { name: string; directory: string };
|
|
@@ -32,8 +39,15 @@ export interface ImportTabCtx {
|
|
|
32
39
|
rerender: () => void;
|
|
33
40
|
/** Called with the imported project; the modal resolves and closes. */
|
|
34
41
|
onDone: (result: { root: string; config: ProjectConfig }) => void;
|
|
35
|
-
/** The modal's shared credentials-form instance, rendered while
|
|
42
|
+
/** The modal's shared credentials-form instance, rendered while the gate is closed. */
|
|
36
43
|
credsForm: CredsFormLike;
|
|
44
|
+
/**
|
|
45
|
+
* Whether AI is usable — a local key OR a backend holding credentials of its own. Also fires the
|
|
46
|
+
* capability probe while closed, so a managed platform's Cloudflare option can appear.
|
|
47
|
+
*/
|
|
48
|
+
aiGateOpen: () => boolean;
|
|
49
|
+
/** The modal's shared keyless "Connect Cloudflare" controller, rendered beside the form. */
|
|
50
|
+
managedConnect: ManagedConnectLike;
|
|
37
51
|
}
|
|
38
52
|
|
|
39
53
|
let _url = "";
|
|
@@ -253,13 +267,17 @@ export function renderImportStatus(): TemplateResult {
|
|
|
253
267
|
}
|
|
254
268
|
|
|
255
269
|
export function renderImportSource(ctx: ImportTabCtx): TemplateResult {
|
|
256
|
-
if (!
|
|
270
|
+
if (!ctx.aiGateOpen()) {
|
|
257
271
|
return html`
|
|
258
272
|
<div class="new-project-tab-intro">
|
|
259
|
-
Importing uses an AI-guided pipeline to clone an existing site.
|
|
260
|
-
|
|
273
|
+
Importing uses an AI-guided pipeline to clone an existing site.
|
|
274
|
+
${
|
|
275
|
+
ctx.managedConnect.canOffer()
|
|
276
|
+
? "Connect Cloudflare, or add an OpenAI-compatible API key, to continue."
|
|
277
|
+
: "Add an OpenAI-compatible API key to continue."
|
|
278
|
+
}
|
|
261
279
|
</div>
|
|
262
|
-
<div class="new-project-creds">${ctx.credsForm.render()}</div>
|
|
280
|
+
<div class="new-project-creds">${ctx.managedConnect.render()} ${ctx.credsForm.render()}</div>
|
|
263
281
|
`;
|
|
264
282
|
}
|
|
265
283
|
|
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
* (colors, fonts, logo, breakpoints — a creation-time subset of the settings modal), prefilled from
|
|
7
7
|
* the chosen source and customizable before anything is written.
|
|
8
8
|
*
|
|
9
|
-
* Import and Agent
|
|
9
|
+
* Import and Agent need working AI, so both are gated until credentials exist — a key stored in
|
|
10
|
+
* this browser, or a backend that holds its own (managed cloud platforms, env-keyed dev servers).
|
|
11
|
+
* While gated they offer the same two paths as the assistant sidebar: connect Cloudflare for
|
|
12
|
+
* Workers AI, or bring a key.
|
|
10
13
|
*/
|
|
11
14
|
|
|
12
15
|
import { html } from "lit-html";
|
|
@@ -14,9 +17,10 @@ import { errorMessage } from "@jxsuite/schema/parse";
|
|
|
14
17
|
import { openModal } from "../ui/layers";
|
|
15
18
|
import { getPlatform } from "../platform";
|
|
16
19
|
import { installUrlOf } from "../platform-errors";
|
|
17
|
-
import {
|
|
20
|
+
import { hasAiCredentials } from "../services/ai-models";
|
|
18
21
|
import { setPendingAgentPrompt } from "../services/agent-seed";
|
|
19
22
|
import { createAiCredentialsForm } from "../ui/ai-credentials-form";
|
|
23
|
+
import { createManagedConnect } from "../ui/ai-managed-connect";
|
|
20
24
|
import { PROJECT_TEMPLATES } from "./templates";
|
|
21
25
|
import { collectDesign, renderDesignFields, resetDesignFields } from "./design-fields";
|
|
22
26
|
import {
|
|
@@ -98,22 +102,44 @@ let _resolve: ((result: { root: string; config: ProjectConfig } | null) => void)
|
|
|
98
102
|
// Before a platform is registered (the form fetches models through the platform on edit).
|
|
99
103
|
let _credsForm: ReturnType<typeof createAiCredentialsForm> | null = null;
|
|
100
104
|
|
|
105
|
+
function rerenderIfOpen() {
|
|
106
|
+
if (_handle) {
|
|
107
|
+
renderModal();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
101
111
|
function credsForm() {
|
|
102
112
|
_credsForm ??= createAiCredentialsForm({
|
|
103
|
-
onSaved:
|
|
104
|
-
|
|
105
|
-
renderModal();
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
requestRender: () => {
|
|
109
|
-
if (_handle) {
|
|
110
|
-
renderModal();
|
|
111
|
-
}
|
|
112
|
-
},
|
|
113
|
+
onSaved: rerenderIfOpen,
|
|
114
|
+
requestRender: rerenderIfOpen,
|
|
113
115
|
});
|
|
114
116
|
return _credsForm;
|
|
115
117
|
}
|
|
116
118
|
|
|
119
|
+
/**
|
|
120
|
+
* The keyless "Connect Cloudflare" option shown beside the key form on managed platforms — the same
|
|
121
|
+
* controller the assistant sidebar uses. Lazy for the same reason as the form above.
|
|
122
|
+
*/
|
|
123
|
+
let _managedConnect: ReturnType<typeof createManagedConnect> | null = null;
|
|
124
|
+
|
|
125
|
+
function managedConnect() {
|
|
126
|
+
_managedConnect ??= createManagedConnect({ requestRender: rerenderIfOpen });
|
|
127
|
+
return _managedConnect;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* The Import and Agent tabs need working AI, which a managed platform can supply without any local
|
|
132
|
+
* key. Probe on every gated render so the Cloudflare option appears as soon as the backend
|
|
133
|
+
* answers.
|
|
134
|
+
*/
|
|
135
|
+
function aiGateOpen(): boolean {
|
|
136
|
+
if (hasAiCredentials()) {
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
managedConnect().ensureProbe();
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
|
|
117
143
|
/**
|
|
118
144
|
* Open the New Project modal. Returns a promise that resolves with the created project info (or
|
|
119
145
|
* null if cancelled).
|
|
@@ -235,8 +261,10 @@ function sourceLabel(): string {
|
|
|
235
261
|
function renderModal() {
|
|
236
262
|
const platform = getPlatform();
|
|
237
263
|
const importCtx: ImportTabCtx = {
|
|
264
|
+
aiGateOpen,
|
|
238
265
|
credsForm: credsForm(),
|
|
239
266
|
form: _form,
|
|
267
|
+
managedConnect: managedConnect(),
|
|
240
268
|
onDone: finish,
|
|
241
269
|
rerender: renderModal,
|
|
242
270
|
resolveDestination: () => validateParams(),
|
|
@@ -469,13 +497,17 @@ function renderModal() {
|
|
|
469
497
|
: html`<div class="new-project-tab-intro">No starter sites are available.</div>`;
|
|
470
498
|
|
|
471
499
|
const agentSourceTpl = () => {
|
|
472
|
-
if (!
|
|
500
|
+
if (!aiGateOpen()) {
|
|
473
501
|
return html`
|
|
474
502
|
<div class="new-project-tab-intro">
|
|
475
|
-
The agent uses your AI provider to build the site.
|
|
476
|
-
|
|
503
|
+
The agent uses your AI provider to build the site.
|
|
504
|
+
${
|
|
505
|
+
managedConnect().canOffer()
|
|
506
|
+
? "Connect Cloudflare, or add an OpenAI-compatible API key, to continue."
|
|
507
|
+
: "Add an OpenAI-compatible API key to continue."
|
|
508
|
+
}
|
|
477
509
|
</div>
|
|
478
|
-
<div class="new-project-creds">${credsForm().render()}</div>
|
|
510
|
+
<div class="new-project-creds">${managedConnect().render()} ${credsForm().render()}</div>
|
|
479
511
|
`;
|
|
480
512
|
}
|
|
481
513
|
return html`
|
|
@@ -597,7 +629,7 @@ function renderModal() {
|
|
|
597
629
|
`;
|
|
598
630
|
}
|
|
599
631
|
if (_step === "source") {
|
|
600
|
-
const gated = (_tab === "import" || _tab === "agent") && !
|
|
632
|
+
const gated = (_tab === "import" || _tab === "agent") && !aiGateOpen();
|
|
601
633
|
return html`
|
|
602
634
|
<sp-button variant="secondary" @click=${closeNewProjectModal}>Cancel</sp-button>
|
|
603
635
|
${gated ? "" : html`<sp-button variant="accent" @click=${goNext}>Next</sp-button>`}
|