@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jxsuite/studio",
3
- "version": "0.35.0",
3
+ "version": "0.36.0",
4
4
  "description": "Jx Studio — visual builder for Jx documents",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -18,7 +18,8 @@
18
18
  ".": "./src/studio.ts",
19
19
  "./platform": "./src/platform.ts",
20
20
  "./types": "./src/types.ts",
21
- "./import-client": "./src/services/import-client.ts"
21
+ "./import-client": "./src/services/import-client.ts",
22
+ "./platforms/cloud": "./src/platforms/cloud.ts"
22
23
  },
23
24
  "publishConfig": {
24
25
  "provenance": true
@@ -38,9 +39,11 @@
38
39
  "@atlaskit/pragmatic-drag-and-drop": "^2.0.1",
39
40
  "@atlaskit/pragmatic-drag-and-drop-hitbox": "^2.0.0",
40
41
  "@jxsuite/ai": "^0.33.0",
41
- "@jxsuite/parser": "^0.35.0",
42
- "@jxsuite/runtime": "^0.34.1",
43
- "@jxsuite/schema": "^0.34.0",
42
+ "@jxsuite/create": "^0.36.0",
43
+ "@jxsuite/parser": "^0.35.1",
44
+ "@jxsuite/protocol": "^0.2.0",
45
+ "@jxsuite/runtime": "^0.34.2",
46
+ "@jxsuite/schema": "^0.35.0",
44
47
  "@spectrum-web-components/accordion": "^1.12.1",
45
48
  "@spectrum-web-components/action-bar": "1.12.1",
46
49
  "@spectrum-web-components/action-button": "^1.12.1",
@@ -21,6 +21,7 @@ import type { TemplateResult } from "lit-html";
21
21
  import { effect, effectScope } from "../reactivity";
22
22
  import { createDocumentAssistant } from "../services/document-assistant";
23
23
  import { hasOpenAiKey } from "../services/ai-settings";
24
+ import { fetchAvailableModels, isProxyConfigured } from "../services/ai-models";
24
25
  import { createAiCredentialsForm } from "../ui/ai-credentials-form";
25
26
  import { clearMarkdownCache } from "./ai-chat/chat-markdown";
26
27
  import { renderChatHeader, renderMessageList } from "./ai-chat/chat-view";
@@ -36,6 +37,23 @@ let mounted = false;
36
37
  /** Whether the OpenAI key form is showing (gate when no key, or re-edit via the gear). */
37
38
  let keyEditing = false;
38
39
 
40
+ /**
41
+ * One-time proxy probe: managed platforms (cloud Workers AI) and env-keyed dev servers report
42
+ * `configured` from /models, unlocking the assistant without a locally stored key. Fired lazily on
43
+ * the first gated render.
44
+ */
45
+ let proxyProbe: Promise<void> | null = null;
46
+
47
+ function ensureProxyProbe() {
48
+ proxyProbe ??= fetchAvailableModels({ force: true })
49
+ .catch(() => {
50
+ // Unreachable proxy — the key gate stays up.
51
+ })
52
+ .then(() => {
53
+ scheduleAiRender();
54
+ });
55
+ }
56
+
39
57
  /** Which pane the panel shows once the key gate is passed. */
40
58
  let view: "chat" | "sessions" = "chat";
41
59
 
@@ -245,9 +263,13 @@ const composer = createComposer({
245
263
 
246
264
  /** @returns {TemplateResult} */
247
265
  export function renderAiPanelTemplate(): TemplateResult {
248
- // The document assistant authenticates via the AI proxy (an OpenAI-compatible key). Gate the chat
249
- // Behind the key form until one is stored locally.
250
- if (!hasOpenAiKey() || keyEditing) {
266
+ /* The document assistant authenticates via the AI proxy. Gate the chat
267
+ behind the key form until a key is stored locally OR the proxy reports
268
+ itself configured (managed platforms, env-keyed dev servers). */
269
+ if ((!hasOpenAiKey() && !isProxyConfigured()) || keyEditing) {
270
+ if (!keyEditing) {
271
+ ensureProxyProbe();
272
+ }
251
273
  return renderKeyGate();
252
274
  }
253
275
 
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import { html, render as litRender, nothing } from "lit-html";
8
+ import { openPublishPanel } from "../publish/publish-panel";
8
9
  import { updateSession } from "../store";
9
10
  import { redo as tabRedo, undo as tabUndo } from "../tabs/transact";
10
11
  import { effect, effectScope } from "../reactivity";
@@ -472,6 +473,7 @@ function toolbarTemplate() {
472
473
  ${recentProjectsTpl}
473
474
  </div>
474
475
  ${tbBtnTpl("Manage", openBrowseModal, "sp-icon-view-list")}
476
+ ${tbBtnTpl("Publish", openPublishPanel)}
475
477
  <sp-action-button size="s" title="Save" ?disabled=${!canSave} @click=${ctx.saveFile}>
476
478
  ${toolbarIconMap["sp-icon-save-floppy"]}<span class="tb-label">Save</span>
477
479
  </sp-action-button>
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import { html, render as litRender, nothing } from "lit-html";
8
+ import { getProjectList } from "../project-list";
8
9
  import { clearRecentProjects, getRecentProjects, removeRecentProject } from "../recent-projects";
9
10
  import { renderOnly } from "../store";
10
11
  import { platformSupportsClone } from "./git-panel";
@@ -27,6 +28,8 @@ export function initWelcome(ctx: WelcomeCtx) {
27
28
  export function renderWelcome(host: HTMLElement) {
28
29
  const ctx = _ctx as WelcomeCtx;
29
30
  const recent = getRecentProjects();
31
+ // Catalogue entries already in Recent stay in that section only.
32
+ const catalogue = getProjectList().filter((p) => !recent.some((r) => r.root === p.root));
30
33
  const showClone = platformSupportsClone();
31
34
 
32
35
  litRender(
@@ -84,6 +87,29 @@ export function renderWelcome(host: HTMLElement) {
84
87
  : nothing}
85
88
  </div>
86
89
 
90
+ ${catalogue.length > 0
91
+ ? html`
92
+ <div class="welcome-section">
93
+ <h2 class="welcome-section-title">Projects</h2>
94
+ ${catalogue.map(
95
+ (p) => html`
96
+ <div class="welcome-recent-row">
97
+ <button
98
+ class="welcome-recent welcome-catalogue"
99
+ @click=${() => ctx.openRecentProject(p.root)}
100
+ title=${p.root}
101
+ >
102
+ <span class="welcome-recent-name">${p.name}</span>
103
+ <span class="welcome-recent-path">
104
+ ${p.description ?? shortenPath(p.root)}
105
+ </span>
106
+ </button>
107
+ </div>
108
+ `,
109
+ )}
110
+ </div>
111
+ `
112
+ : nothing}
87
113
  ${recent.length > 0
88
114
  ? html`
89
115
  <div class="welcome-section">