@yugoo-design/dsh-design-studio-dsh 0.1.0-beta.1 → 0.1.0-beta.3

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/README.md CHANGED
@@ -11,4 +11,18 @@ explicit `kitSources` mode remains available with its strict startup validation.
11
11
 
12
12
  The Remote exposes exactly four read methods: `workspace`, `readKitWorkspace` (exact `name@version` pin required; a diverging response identity diagnoses), `readBundleWorkspace`, and `readBundleFile`. The catalog snapshot projects `ctx.design.listKits()`. Bundle source reads run through `ctx.fs`: the `kitSources` config lists installed content packages (`packageName`, resolved like the Design Core kit-loader) or absolute directories (`root`); every path resolves through the filesystem capability and must stay canonically contained in a configured root, so traversal and symlink escapes never read outside the authored trees and non-UTF-8 content diagnoses as binary. Invalid or ambiguous configuration — a missing root, a root without `mindset.md`, a relative path, a duplicate root, or one Kit/Bundle name declared by two roots — fails loud at startup. Without `kitSources` the catalog stays readable and Bundle reads diagnose `studio.source_not_configured`. Disposal rejects new work and drains admitted calls.
13
13
 
14
- The Settings surface presents the read-only Studio's scope and opens the plugin-owned same-origin route `/design-studio/` through a standard `rel="noopener noreferrer"` anchor. G/R/A loops publish independently and therefore expose no atomic-set size preference here. The route is registered through the public `webServer.register` seam (exact slash-less redirect plus prefix) and withdrawn on disposal. It serves one HTML shell and one self-contained page bundle. That bundle calls only the session-free `studioManagement` read methods through a narrow same-origin `/api` adapter; it does not start the DSH SPA module loader, client plugin runtime, connection registry, commands, or goals. The adapter validates the gateway response and the generated Typert result before rendering the unchanged shared `StudioWorkspace`. Page disposal only unmounts the rendered root. A future Codex or Claude Code companion server serves the same page bundle and implements the same JSON read methods rather than introducing another Studio format.
14
+ Strict codecs follow the current Typert `create(): TypertSchema` factory contract.
15
+ The existing Zod validators supply that parser capability; both Host registration
16
+ and the same-origin page transport consume the same descriptor. Only the two
17
+ optional Bundle-version parameters permit omitted wire fields; required fields,
18
+ invalid types and strict result validation retain their original constraints.
19
+
20
+ The Settings surface presents the read-only Studio's scope and opens the plugin-owned same-origin route `/design-studio/`. HTTP(S) Web uses a separate `target="_blank" rel="noopener noreferrer"` page and retains the conversation tab. On the official Desktop application's exact `dsh-app://app` authority, the launcher navigates in the current window: Desktop rejects new windows on its application protocol. The Desktop Studio page adds a compact **Back to conversation / 返回对话** link to the same-origin application root `/`, without changing the shared `StudioWorkspace`. It never consumes a `returnTo` parameter, referrer, private boot API, backend port, or copied credentials. The host owns conversation and Panel restoration when its application reloads; source and adapter tests do not establish that native round trip.
21
+
22
+ G/R/A loops publish independently and therefore expose no atomic-set size preference here. The route is registered through the public `webServer.register` seam (exact slash-less redirect plus prefix) and withdrawn on disposal. It serves one HTML shell and one self-contained page bundle. That bundle calls only the session-free `studioManagement` read methods through a narrow same-origin `/api` adapter; on Desktop, requests remain on `dsh-app://app` even when the custom scheme reports an opaque (`null`) origin, using the host's existing protocol proxy. It does not start the DSH SPA module loader, client plugin runtime, connection registry, commands, or goals. The adapter validates the gateway response and the generated Typert result before rendering the unchanged shared `StudioWorkspace`. Page disposal only unmounts the rendered root. A future Codex or Claude Code companion server serves the same page bundle and implements the same JSON read methods rather than introducing another Studio format.
23
+
24
+ The standalone page bundles its React runtime and fails the build on unresolved
25
+ dependencies or remaining static/dynamic module imports. Its page-route test also
26
+ checks the emitted JavaScript with the shared loader analyzer and exercises real
27
+ bundler rejection cases. These checks establish browser module closure; rendered
28
+ Host interaction remains a separate integration check.
@@ -1,4 +1,4 @@
1
- import { t as STUDIO_PAGE_BASE } from "./page-path-Nt6gFiV-.js";
1
+ import { t as STUDIO_PAGE_BASE } from "./page-path-wn8e_fid.js";
2
2
  import { ReactElement } from "react";
3
3
  import { SettingsSectionOwnerProps } from "@deepseek-ai/dsh-client-ui-settings/client";
4
4
  import { StudioManagementClient } from "@yugoo-design/dsh-design-studio-ui";
@@ -38,15 +38,16 @@ interface DshStudioRemote {
38
38
  /** Build the shared client over DSH's generated Remote namespace. */
39
39
  declare function createDshStudioClient(remote: DshStudioRemote): StudioManagementClient;
40
40
  /**
41
- * Settings-shell launcher for the full-page Studio workspace. The link is a
42
- * standard noopener anchor, so it is always clickable and copyable, never
43
- * hands the host window to the Studio page, and needs no popup inference.
41
+ * Settings-shell launcher for the full-page Studio workspace. Web opens a
42
+ * separate noopener page; Desktop follows its existing same-window app route.
44
43
  * @param actions - Settings owner affordances.
45
44
  * @returns the launcher element.
46
45
  */
47
46
  declare function renderStudioLauncher(actions: {
48
47
  close(): void;
49
- }, zh?: boolean): ReactElement;
48
+ }, zh?: boolean, locationHref?: string): ReactElement;
49
+ /** Compact Desktop page navigation, independent of the shared Studio workspace. */
50
+ declare function renderStudioReturnNavigation(zh?: boolean, locationHref?: string): ReactElement | null;
50
51
  /** Design Studio settings page with the launcher only. */
51
52
  declare function DshStudioSettingsSection(props: DshStudioSettingsSectionProps): ReactElement;
52
53
  /** Minimal slot face required to install the Studio Settings contribution. */
@@ -59,4 +60,4 @@ declare function registerDshStudioSettings(host: {
59
60
  readonly slots: DshStudioSlots;
60
61
  } & DshStudioSettingsRuntime): void;
61
62
  //#endregion
62
- export { DshRemoteResult, DshStudioRemote, DshStudioSettingsRuntime, DshStudioSettingsSection, DshStudioSlots, STUDIO_PAGE_BASE as STUDIO_PAGE_URL, createDshStudioClient, registerDshStudioSettings, renderStudioLauncher };
63
+ export { DshRemoteResult, DshStudioRemote, DshStudioSettingsRuntime, DshStudioSettingsSection, DshStudioSlots, STUDIO_PAGE_BASE as STUDIO_PAGE_URL, createDshStudioClient, registerDshStudioSettings, renderStudioLauncher, renderStudioReturnNavigation };
@@ -1,4 +1,4 @@
1
- import { STUDIO_PAGE_BASE } from "./page-path.js";
1
+ import { STUDIO_PAGE_BASE, isDshDesktopLocation, studioConversationReturnPath } from "./page-path.js";
2
2
  import { useSyncExternalStore } from "react";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  //#region src/client-adapter.tsx
@@ -50,13 +50,13 @@ function createDshStudioClient(remote) {
50
50
  });
51
51
  }
52
52
  /**
53
- * Settings-shell launcher for the full-page Studio workspace. The link is a
54
- * standard noopener anchor, so it is always clickable and copyable, never
55
- * hands the host window to the Studio page, and needs no popup inference.
53
+ * Settings-shell launcher for the full-page Studio workspace. Web opens a
54
+ * separate noopener page; Desktop follows its existing same-window app route.
56
55
  * @param actions - Settings owner affordances.
57
56
  * @returns the launcher element.
58
57
  */
59
- function renderStudioLauncher(actions, zh = false) {
58
+ function renderStudioLauncher(actions, zh = false, locationHref = globalThis.location?.href) {
59
+ const desktop = isDshDesktopLocation(locationHref);
60
60
  return /* @__PURE__ */ jsxs("div", {
61
61
  className: "ygd-studio-launcher",
62
62
  style: cardStyle,
@@ -79,7 +79,7 @@ function renderStudioLauncher(actions, zh = false) {
79
79
  ...secondaryTextStyle,
80
80
  margin: "6px 0 0"
81
81
  },
82
- children: zh ? "在独立页面中查看预制 Kit、Mindset、挂载的 Bundles 及其源文件。打开 Studio 不会中断当前对话。" : "Inspect shipped Kits, Mindsets, mounted Bundles, and their source files in a dedicated workspace. Opening Studio leaves this conversation untouched."
82
+ children: desktop ? zh ? "在当前窗口中查看预制 Kit、Mindset、挂载的 Bundles 及其源文件。查看后可点击「返回对话」。" : "Inspect shipped Kits, Mindsets, mounted Bundles, and their source files in this window. Use “Back to conversation” to return." : zh ? "在独立页面中查看预制 Kit、Mindset、挂载的 Bundles 及其源文件。打开 Studio 不会中断当前对话。" : "Inspect shipped Kits, Mindsets, mounted Bundles, and their source files in a dedicated workspace. Opening Studio leaves this conversation untouched."
83
83
  })] }), /* @__PURE__ */ jsx("span", {
84
84
  style: {
85
85
  flex: "0 0 auto",
@@ -102,8 +102,8 @@ function renderStudioLauncher(actions, zh = false) {
102
102
  children: [/* @__PURE__ */ jsx("a", {
103
103
  className: "ygd-studio-launch-link",
104
104
  href: STUDIO_PAGE_BASE,
105
- target: "_blank",
106
- rel: "noopener noreferrer",
105
+ target: desktop ? "_self" : "_blank",
106
+ rel: desktop ? void 0 : "noopener noreferrer",
107
107
  onClick: () => actions.close(),
108
108
  style: {
109
109
  display: "inline-flex",
@@ -130,6 +130,43 @@ function renderStudioLauncher(actions, zh = false) {
130
130
  })]
131
131
  });
132
132
  }
133
+ /** Compact Desktop page navigation, independent of the shared Studio workspace. */
134
+ function renderStudioReturnNavigation(zh = false, locationHref = globalThis.location?.href) {
135
+ const returnPath = studioConversationReturnPath(locationHref);
136
+ if (returnPath === void 0) return null;
137
+ return /* @__PURE__ */ jsx("nav", {
138
+ "aria-label": zh ? "应用导航" : "Application navigation",
139
+ className: "ygd-studio-return-navigation",
140
+ style: {
141
+ display: "flex",
142
+ alignItems: "center",
143
+ flex: "0 0 auto",
144
+ padding: "8px 12px",
145
+ borderBottom: "1px solid var(--dsw-alias-border-l1, #E8E8E8)",
146
+ background: "var(--dsw-alias-bg-layer-1, #FFFFFF)",
147
+ fontFamily: "'PingFang SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Microsoft YaHei', sans-serif"
148
+ },
149
+ children: /* @__PURE__ */ jsxs("a", {
150
+ href: returnPath,
151
+ target: "_self",
152
+ style: {
153
+ display: "inline-flex",
154
+ alignItems: "center",
155
+ gap: 6,
156
+ minHeight: 32,
157
+ padding: "0 8px",
158
+ borderRadius: 6,
159
+ color: "var(--dsw-alias-label-primary, #272727)",
160
+ fontSize: 13,
161
+ textDecoration: "none"
162
+ },
163
+ children: [/* @__PURE__ */ jsx("span", {
164
+ "aria-hidden": "true",
165
+ children: "←"
166
+ }), zh ? "返回对话" : "Back to conversation"]
167
+ })
168
+ });
169
+ }
133
170
  /** Design Studio settings page with the launcher only. */
134
171
  function DshStudioSettingsSection(props) {
135
172
  const zh = useSyncExternalStore((listener) => props.locale.subscribe(listener), () => props.locale.getSnapshot(), () => props.locale.getSnapshot()).active === "zh";
@@ -167,4 +204,4 @@ function registerDshStudioSettings(host) {
167
204
  }, Section));
168
205
  }
169
206
  //#endregion
170
- export { DshStudioSettingsSection, STUDIO_PAGE_BASE as STUDIO_PAGE_URL, createDshStudioClient, registerDshStudioSettings, renderStudioLauncher };
207
+ export { DshStudioSettingsSection, STUDIO_PAGE_BASE as STUDIO_PAGE_URL, createDshStudioClient, registerDshStudioSettings, renderStudioLauncher, renderStudioReturnNavigation };
package/lib/client.js CHANGED
@@ -10,6 +10,16 @@ window.__ModuleLoader__.load({
10
10
  /** Browser-safe path constants shared by the host route and the launcher. */
11
11
  /** Base path owned by the Studio page route. */
12
12
  const STUDIO_PAGE_BASE = "/design-studio/";
13
+ /** Recognize only the official Desktop application authority, not a redirect hint. */
14
+ function isDshDesktopLocation(href = globalThis.location?.href) {
15
+ if (href === void 0) return false;
16
+ try {
17
+ const url = new URL(href);
18
+ return url.protocol === "dsh-app:" && url.host === "app" && url.username === "" && url.password === "";
19
+ } catch {
20
+ return false;
21
+ }
22
+ }
13
23
  //#endregion
14
24
  //#region src/client-adapter.tsx
15
25
  /** Shared DSH browser adapter values, independently testable from client boot. */
@@ -32,13 +42,13 @@ window.__ModuleLoader__.load({
32
42
  lineHeight: 1.55
33
43
  };
34
44
  /**
35
- * Settings-shell launcher for the full-page Studio workspace. The link is a
36
- * standard noopener anchor, so it is always clickable and copyable, never
37
- * hands the host window to the Studio page, and needs no popup inference.
45
+ * Settings-shell launcher for the full-page Studio workspace. Web opens a
46
+ * separate noopener page; Desktop follows its existing same-window app route.
38
47
  * @param actions - Settings owner affordances.
39
48
  * @returns the launcher element.
40
49
  */
41
- function renderStudioLauncher(actions, zh = false) {
50
+ function renderStudioLauncher(actions, zh = false, locationHref = globalThis.location?.href) {
51
+ const desktop = isDshDesktopLocation(locationHref);
42
52
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
43
53
  className: "ygd-studio-launcher",
44
54
  style: cardStyle,
@@ -61,7 +71,7 @@ window.__ModuleLoader__.load({
61
71
  ...secondaryTextStyle,
62
72
  margin: "6px 0 0"
63
73
  },
64
- children: zh ? "在独立页面中查看预制 Kit、Mindset、挂载的 Bundles 及其源文件。打开 Studio 不会中断当前对话。" : "Inspect shipped Kits, Mindsets, mounted Bundles, and their source files in a dedicated workspace. Opening Studio leaves this conversation untouched."
74
+ children: desktop ? zh ? "在当前窗口中查看预制 Kit、Mindset、挂载的 Bundles 及其源文件。查看后可点击「返回对话」。" : "Inspect shipped Kits, Mindsets, mounted Bundles, and their source files in this window. Use “Back to conversation” to return." : zh ? "在独立页面中查看预制 Kit、Mindset、挂载的 Bundles 及其源文件。打开 Studio 不会中断当前对话。" : "Inspect shipped Kits, Mindsets, mounted Bundles, and their source files in a dedicated workspace. Opening Studio leaves this conversation untouched."
65
75
  })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
66
76
  style: {
67
77
  flex: "0 0 auto",
@@ -84,8 +94,8 @@ window.__ModuleLoader__.load({
84
94
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
85
95
  className: "ygd-studio-launch-link",
86
96
  href: STUDIO_PAGE_BASE,
87
- target: "_blank",
88
- rel: "noopener noreferrer",
97
+ target: desktop ? "_self" : "_blank",
98
+ rel: desktop ? void 0 : "noopener noreferrer",
89
99
  onClick: () => actions.close(),
90
100
  style: {
91
101
  display: "inline-flex",
@@ -1,7 +1,7 @@
1
1
  //#region \0rolldown/runtime.js
2
2
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
3
3
  //#endregion
4
- //#region ../../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js
4
+ //#region ../../../cx1-web-rc2-upgrade-20261014/node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js
5
5
  /**
6
6
  * @license React
7
7
  * react.production.min.js
@@ -343,12 +343,12 @@ var require_react_production_min = /* @__PURE__ */ __commonJSMin(((exports) => {
343
343
  exports.version = "18.3.1";
344
344
  }));
345
345
  //#endregion
346
- //#region ../../node_modules/.pnpm/react@18.3.1/node_modules/react/index.js
346
+ //#region ../../../cx1-web-rc2-upgrade-20261014/node_modules/.pnpm/react@18.3.1/node_modules/react/index.js
347
347
  var require_react = /* @__PURE__ */ __commonJSMin(((exports, module) => {
348
348
  module.exports = require_react_production_min();
349
349
  }));
350
350
  //#endregion
351
- //#region ../../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
351
+ //#region ../../../cx1-web-rc2-upgrade-20261014/node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
352
352
  /**
353
353
  * @license React
354
354
  * scheduler.production.min.js
@@ -603,12 +603,12 @@ var require_scheduler_production_min = /* @__PURE__ */ __commonJSMin(((exports)
603
603
  };
604
604
  }));
605
605
  //#endregion
606
- //#region ../../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/index.js
606
+ //#region ../../../cx1-web-rc2-upgrade-20261014/node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/index.js
607
607
  var require_scheduler = /* @__PURE__ */ __commonJSMin(((exports, module) => {
608
608
  module.exports = require_scheduler_production_min();
609
609
  }));
610
610
  //#endregion
611
- //#region ../../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
611
+ //#region ../../../cx1-web-rc2-upgrade-20261014/node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
612
612
  /**
613
613
  * @license React
614
614
  * react-dom.production.min.js
@@ -7465,7 +7465,7 @@ var require_react_dom_production_min = /* @__PURE__ */ __commonJSMin(((exports)
7465
7465
  exports.version = "18.3.1-next-f1338f8080-20240426";
7466
7466
  }));
7467
7467
  //#endregion
7468
- //#region ../../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/index.js
7468
+ //#region ../../../cx1-web-rc2-upgrade-20261014/node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/index.js
7469
7469
  var require_react_dom = /* @__PURE__ */ __commonJSMin(((exports, module) => {
7470
7470
  function checkDCE() {
7471
7471
  if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined" || typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== "function") return;
@@ -7479,14 +7479,14 @@ var require_react_dom = /* @__PURE__ */ __commonJSMin(((exports, module) => {
7479
7479
  module.exports = require_react_dom_production_min();
7480
7480
  }));
7481
7481
  //#endregion
7482
- //#region ../../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/client.js
7482
+ //#region ../../../cx1-web-rc2-upgrade-20261014/node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/client.js
7483
7483
  var require_client = /* @__PURE__ */ __commonJSMin(((exports) => {
7484
7484
  var m = require_react_dom();
7485
7485
  exports.createRoot = m.createRoot;
7486
7486
  exports.hydrateRoot = m.hydrateRoot;
7487
7487
  }));
7488
7488
  //#endregion
7489
- //#region ../../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react-jsx-runtime.production.min.js
7489
+ //#region ../../../cx1-web-rc2-upgrade-20261014/node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react-jsx-runtime.production.min.js
7490
7490
  /**
7491
7491
  * @license React
7492
7492
  * react-jsx-runtime.production.min.js
@@ -7529,7 +7529,7 @@ var require_react_jsx_runtime_production_min = /* @__PURE__ */ __commonJSMin(((e
7529
7529
  exports.jsxs = q;
7530
7530
  }));
7531
7531
  //#endregion
7532
- //#region ../../node_modules/.pnpm/react@18.3.1/node_modules/react/jsx-runtime.js
7532
+ //#region ../../../cx1-web-rc2-upgrade-20261014/node_modules/.pnpm/react@18.3.1/node_modules/react/jsx-runtime.js
7533
7533
  var require_jsx_runtime = /* @__PURE__ */ __commonJSMin(((exports, module) => {
7534
7534
  module.exports = require_react_jsx_runtime_production_min();
7535
7535
  }));
@@ -8582,6 +8582,9 @@ const STUDIO_WORKSPACE_CSS = `
8582
8582
  /* Responsive */
8583
8583
  /* Demo geometry, Yugoo brand tokens: one hero, one document toolbar, one body. */
8584
8584
  .ygd-studio-content-header .ygd-studio-btn-primary,.ygd-studio-content-header .ygd-studio-btn-link{margin:0}
8585
+ .ygd-studio-content-header .ygd-studio-catalog-link{display:inline-flex;align-items:center;gap:6px;min-height:32px;max-width:100%;margin:0 0 0 auto;color:var(--ds-primary-dark);text-decoration:none;overflow-wrap:anywhere}
8586
+ .ygd-studio-catalog-link svg{flex-shrink:0}
8587
+ .ygd-studio-catalog-link:focus-visible{outline:2px solid var(--ds-primary);outline-offset:2px}
8585
8588
  .ygd-studio-sidebar-nav{padding:0}
8586
8589
  .ygd-studio-sidebar-item{display:flex;align-items:center;gap:10px}
8587
8590
  .ygd-studio-sidebar-item .ygd-studio-kitmark{width:18px;height:18px;background:none;color:inherit;border-radius:0}
@@ -11830,6 +11833,7 @@ function ContentArchiveWorkbench({ client, installedKit, locale, canAdoptKit, on
11830
11833
  /** Reusable host-neutral React workspace for the read-only Kit-first Studio surface. */
11831
11834
  const KIT_TABS = ["mindset", "mounts"];
11832
11835
  const TABPANEL_ID = "ygd-studio-kit-tabpanel";
11836
+ const OFFICIAL_KITS_URL = "https://github.com/alibaba-damo-academy/yugoo-design/blob/main/docs/wiki/kit-sharing.md#official-kits";
11833
11837
  const displayName = (name) => name.replace(/[_-]+/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
11834
11838
  function InlineMindset(props) {
11835
11839
  const [initialId] = (0, import_react.useState)(props.initialId);
@@ -11849,6 +11853,8 @@ const STRINGS = {
11849
11853
  kitsTitle: "Kits",
11850
11854
  kitsContext: "Studio 1.0 · Kits",
11851
11855
  kitsSubtitle: "Manage domain methods and mounted Bundles.",
11856
+ browseOfficialKits: "Browse official kits",
11857
+ officialKitsHelp: "Browse official kits: descriptions and acquisition guidance (opens in a new tab)",
11852
11858
  bundlesTitle: "Bundles",
11853
11859
  bundlesContext: "Studio 1.0 · Bundles",
11854
11860
  bundlesSubtitle: "Installed Bundles, read-only inspection",
@@ -11899,6 +11905,8 @@ const STRINGS = {
11899
11905
  kitsTitle: "设计套件",
11900
11906
  kitsContext: "Studio 1.0 · 设计套件",
11901
11907
  kitsSubtitle: "管理领域方法与技能包挂载。",
11908
+ browseOfficialKits: "浏览官方设计套件",
11909
+ officialKitsHelp: "浏览官方设计套件:简介和获取指引(在新标签页打开)",
11902
11910
  bundlesTitle: "技能包",
11903
11911
  bundlesContext: "Studio 1.0 · 技能包",
11904
11912
  bundlesSubtitle: "只读查看已安装技能包",
@@ -12910,16 +12918,37 @@ function StudioWorkspace({ client, controller: supplied, authoring, kitAuthoring
12910
12918
  className: "ygd-studio-main",
12911
12919
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("header", {
12912
12920
  className: "ygd-studio-content-header",
12913
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
12914
- className: "ygd-studio-header-title-group",
12915
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
12916
- className: "ygd-studio-page-title",
12917
- children: t.kitsTitle
12921
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
12922
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
12923
+ className: "ygd-studio-header-title-group",
12924
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
12925
+ className: "ygd-studio-page-title",
12926
+ children: t.kitsTitle
12927
+ })
12928
+ }),
12929
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
12930
+ className: "ygd-studio-subtitle",
12931
+ children: t.kitsSubtitle
12932
+ }),
12933
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", {
12934
+ className: "ygd-studio-btn-link ygd-studio-catalog-link",
12935
+ href: OFFICIAL_KITS_URL,
12936
+ target: "_blank",
12937
+ rel: "noopener noreferrer",
12938
+ title: t.officialKitsHelp,
12939
+ "aria-label": t.officialKitsHelp,
12940
+ children: [t.browseOfficialKits, /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
12941
+ width: "14",
12942
+ height: "14",
12943
+ viewBox: "0 0 24 24",
12944
+ fill: "none",
12945
+ stroke: "currentColor",
12946
+ strokeWidth: "1.7",
12947
+ "aria-hidden": "true",
12948
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M14 3h7v7M10 14 21 3M21 14v6a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h6" })
12949
+ })]
12918
12950
  })
12919
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
12920
- className: "ygd-studio-subtitle",
12921
- children: t.kitsSubtitle
12922
- })] })
12951
+ ] })
12923
12952
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
12924
12953
  className: "ygd-studio-content-body",
12925
12954
  children: [
@@ -13454,6 +13483,22 @@ function StudioWorkspace({ client, controller: supplied, authoring, kitAuthoring
13454
13483
  ]
13455
13484
  });
13456
13485
  }
13486
+ /** Recognize only the official Desktop application authority, not a redirect hint. */
13487
+ function isDshDesktopLocation(href = globalThis.location?.href) {
13488
+ if (href === void 0) return false;
13489
+ try {
13490
+ const url = new URL(href);
13491
+ return url.protocol === "dsh-app:" && url.host === "app" && url.username === "" && url.password === "";
13492
+ } catch {
13493
+ return false;
13494
+ }
13495
+ }
13496
+ /** Desktop returns through the known application root; no caller-controlled redirect. */
13497
+ function studioConversationReturnPath(href = globalThis.location?.href) {
13498
+ if (!isDshDesktopLocation(href)) return void 0;
13499
+ const { pathname } = new URL(href);
13500
+ return pathname === "/design-studio/" || pathname === "/design-studio" ? "/" : void 0;
13501
+ }
13457
13502
  //#endregion
13458
13503
  //#region src/client-adapter.tsx
13459
13504
  /** Shared DSH browser adapter values, independently testable from client boot. */
@@ -13485,8 +13530,45 @@ function createDshStudioClient(remote) {
13485
13530
  readBundleFile: (input) => unwrap("readBundleFile", remote.readBundleFile(input.name, input.path, input.version))
13486
13531
  });
13487
13532
  }
13533
+ /** Compact Desktop page navigation, independent of the shared Studio workspace. */
13534
+ function renderStudioReturnNavigation(zh = false, locationHref = globalThis.location?.href) {
13535
+ const returnPath = studioConversationReturnPath(locationHref);
13536
+ if (returnPath === void 0) return null;
13537
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("nav", {
13538
+ "aria-label": zh ? "应用导航" : "Application navigation",
13539
+ className: "ygd-studio-return-navigation",
13540
+ style: {
13541
+ display: "flex",
13542
+ alignItems: "center",
13543
+ flex: "0 0 auto",
13544
+ padding: "8px 12px",
13545
+ borderBottom: "1px solid var(--dsw-alias-border-l1, #E8E8E8)",
13546
+ background: "var(--dsw-alias-bg-layer-1, #FFFFFF)",
13547
+ fontFamily: "'PingFang SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Microsoft YaHei', sans-serif"
13548
+ },
13549
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", {
13550
+ href: returnPath,
13551
+ target: "_self",
13552
+ style: {
13553
+ display: "inline-flex",
13554
+ alignItems: "center",
13555
+ gap: 6,
13556
+ minHeight: 32,
13557
+ padding: "0 8px",
13558
+ borderRadius: 6,
13559
+ color: "var(--dsw-alias-label-primary, #272727)",
13560
+ fontSize: 13,
13561
+ textDecoration: "none"
13562
+ },
13563
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
13564
+ "aria-hidden": "true",
13565
+ children: "←"
13566
+ }), zh ? "返回对话" : "Back to conversation"]
13567
+ })
13568
+ });
13569
+ }
13488
13570
  //#endregion
13489
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/core.js
13571
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/core.js
13490
13572
  var _a$1;
13491
13573
  function $constructor(name, initializer, params) {
13492
13574
  function init(inst, def) {
@@ -13545,7 +13627,7 @@ function config(newConfig) {
13545
13627
  return globalConfig;
13546
13628
  }
13547
13629
  //#endregion
13548
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/util.js
13630
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/util.js
13549
13631
  function getEnumValues(entries) {
13550
13632
  const numericValues = Object.values(entries).filter((v) => typeof v === "number");
13551
13633
  return Object.entries(entries).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
@@ -13859,7 +13941,7 @@ function issue(...args) {
13859
13941
  return { ...iss };
13860
13942
  }
13861
13943
  //#endregion
13862
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/errors.js
13944
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/errors.js
13863
13945
  const initializer$1 = (inst, def) => {
13864
13946
  inst.name = "$ZodError";
13865
13947
  Object.defineProperty(inst, "_zod", {
@@ -13919,7 +14001,7 @@ function formatError(error, mapper = (issue) => issue.message) {
13919
14001
  return fieldErrors;
13920
14002
  }
13921
14003
  //#endregion
13922
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/parse.js
14004
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/parse.js
13923
14005
  const _parse = (_Err) => (schema, value, _ctx, _params) => {
13924
14006
  const ctx = _ctx ? {
13925
14007
  ..._ctx,
@@ -14033,7 +14115,7 @@ const _safeDecodeAsync = (_Err) => async (schema, value, _ctx) => {
14033
14115
  return _safeParseAsync(_Err)(schema, value, _ctx);
14034
14116
  };
14035
14117
  //#endregion
14036
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/regexes.js
14118
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/regexes.js
14037
14119
  /**
14038
14120
  * @deprecated CUID v1 is deprecated by its authors due to information leakage
14039
14121
  * (timestamps embedded in the id). Use {@link cuid2} instead.
@@ -14097,7 +14179,7 @@ const boolean$1 = /^(?:true|false)$/i;
14097
14179
  const lowercase = /^[^A-Z]*$/;
14098
14180
  const uppercase = /^[^a-z]*$/;
14099
14181
  //#endregion
14100
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/checks.js
14182
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/checks.js
14101
14183
  const $ZodCheck = /*@__PURE__*/ $constructor("$ZodCheck", (inst, def) => {
14102
14184
  var _a;
14103
14185
  inst._zod ?? (inst._zod = {});
@@ -14459,7 +14541,7 @@ const $ZodCheckOverwrite = /*@__PURE__*/ $constructor("$ZodCheckOverwrite", (ins
14459
14541
  };
14460
14542
  });
14461
14543
  //#endregion
14462
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/doc.js
14544
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/doc.js
14463
14545
  var Doc = class {
14464
14546
  constructor(args = []) {
14465
14547
  this.content = [];
@@ -14490,14 +14572,14 @@ var Doc = class {
14490
14572
  }
14491
14573
  };
14492
14574
  //#endregion
14493
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/versions.js
14575
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/versions.js
14494
14576
  const version = {
14495
14577
  major: 4,
14496
14578
  minor: 4,
14497
14579
  patch: 3
14498
14580
  };
14499
14581
  //#endregion
14500
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/schemas.js
14582
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/schemas.js
14501
14583
  const $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => {
14502
14584
  var _a;
14503
14585
  inst ?? (inst = {});
@@ -15727,7 +15809,7 @@ function handleRefineResult(result, payload, input, inst) {
15727
15809
  }
15728
15810
  }
15729
15811
  //#endregion
15730
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/registries.js
15812
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/registries.js
15731
15813
  var _a;
15732
15814
  var $ZodRegistry = class {
15733
15815
  constructor() {
@@ -15774,7 +15856,7 @@ function registry() {
15774
15856
  (_a = globalThis).__zod_globalRegistry ?? (_a.__zod_globalRegistry = registry());
15775
15857
  const globalRegistry = globalThis.__zod_globalRegistry;
15776
15858
  //#endregion
15777
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/api.js
15859
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/api.js
15778
15860
  // @__NO_SIDE_EFFECTS__
15779
15861
  function _string(Class, params) {
15780
15862
  return new Class({
@@ -16279,7 +16361,7 @@ function _check(fn, params) {
16279
16361
  return ch;
16280
16362
  }
16281
16363
  //#endregion
16282
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/to-json-schema.js
16364
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/to-json-schema.js
16283
16365
  function initializeContext(params) {
16284
16366
  let target = params?.target ?? "draft-2020-12";
16285
16367
  if (target === "draft-4") target = "draft-04";
@@ -16574,7 +16656,7 @@ const createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params)
16574
16656
  return finalize(ctx, schema);
16575
16657
  };
16576
16658
  //#endregion
16577
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/json-schema-processors.js
16659
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/json-schema-processors.js
16578
16660
  const formatMap = {
16579
16661
  guid: "uuid",
16580
16662
  url: "uri",
@@ -16839,7 +16921,7 @@ const optionalProcessor = (schema, ctx, _json, params) => {
16839
16921
  seen.ref = def.innerType;
16840
16922
  };
16841
16923
  //#endregion
16842
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/iso.js
16924
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/iso.js
16843
16925
  const ZodISODateTime = /*@__PURE__*/ $constructor("ZodISODateTime", (inst, def) => {
16844
16926
  $ZodISODateTime.init(inst, def);
16845
16927
  ZodStringFormat.init(inst, def);
@@ -16869,7 +16951,7 @@ function duration(params) {
16869
16951
  return /* @__PURE__ */ _isoDuration(ZodISODuration, params);
16870
16952
  }
16871
16953
  //#endregion
16872
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/errors.js
16954
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/errors.js
16873
16955
  const initializer = (inst, issues) => {
16874
16956
  $ZodError.init(inst, issues);
16875
16957
  inst.name = "ZodError";
@@ -16891,7 +16973,7 @@ const initializer = (inst, issues) => {
16891
16973
  };
16892
16974
  const ZodRealError = /*@__PURE__*/ $constructor("ZodError", initializer, { Parent: Error });
16893
16975
  //#endregion
16894
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/parse.js
16976
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/parse.js
16895
16977
  const parse = /* @__PURE__ */ _parse(ZodRealError);
16896
16978
  const parseAsync = /* @__PURE__ */ _parseAsync(ZodRealError);
16897
16979
  const safeParse = /* @__PURE__ */ _safeParse(ZodRealError);
@@ -16905,7 +16987,7 @@ const safeDecode = /* @__PURE__ */ _safeDecode(ZodRealError);
16905
16987
  const safeEncodeAsync = /* @__PURE__ */ _safeEncodeAsync(ZodRealError);
16906
16988
  const safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync(ZodRealError);
16907
16989
  //#endregion
16908
- //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/schemas.js
16990
+ //#region ../../../cx3-git-library-20261016/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/schemas.js
16909
16991
  const _installedGroups = /* @__PURE__ */ new WeakMap();
16910
16992
  function _installLazyMethods(inst, group, methods) {
16911
16993
  const proto = Object.getPrototypeOf(inst);
@@ -17711,12 +17793,20 @@ const diagnostic = object({
17711
17793
  message: string(),
17712
17794
  subject: string().optional()
17713
17795
  }).strict();
17796
+ const relationText = object({
17797
+ zh: string(),
17798
+ en: string()
17799
+ }).strict();
17714
17800
  const kitView = object({
17715
17801
  name: string(),
17716
- version: string()
17802
+ version: string(),
17803
+ description: string().optional(),
17804
+ displayDescription: relationText.optional()
17717
17805
  }).strict();
17718
17806
  const bundleView = pin.extend({
17719
17807
  description: string(),
17808
+ title: relationText.optional(),
17809
+ displayDescription: relationText.optional(),
17720
17810
  usedBy: array(kitView)
17721
17811
  }).strict();
17722
17812
  const workspace = object({
@@ -17726,16 +17816,14 @@ const workspace = object({
17726
17816
  }).strict();
17727
17817
  const mountView = pin.extend({
17728
17818
  description: string(),
17819
+ title: relationText.optional(),
17820
+ displayDescription: relationText.optional(),
17729
17821
  mountedBy: array(kitView)
17730
17822
  }).strict();
17731
17823
  const resourceView = object({
17732
17824
  path: string(),
17733
17825
  bytes: number().int().nonnegative()
17734
17826
  }).strict();
17735
- const relationText = object({
17736
- zh: string(),
17737
- en: string()
17738
- }).strict();
17739
17827
  const relationView = object({
17740
17828
  type: string(),
17741
17829
  meaning: string(),
@@ -17766,6 +17854,7 @@ const kitWorkspaceResult = object({
17766
17854
  name: string(),
17767
17855
  version: string(),
17768
17856
  description: string(),
17857
+ displayDescription: relationText.optional(),
17769
17858
  mindsetSource: string(),
17770
17859
  mounts: array(mountView),
17771
17860
  resources: array(resourceView),
@@ -17791,6 +17880,7 @@ const bundleWorkspaceResult = object({
17791
17880
  version: string(),
17792
17881
  kit: string().optional(),
17793
17882
  description: string(),
17883
+ displayDescription: relationText.optional(),
17794
17884
  files: array(bundleFileRef),
17795
17885
  manifest: record(string(), unknown()).optional(),
17796
17886
  schema: record(string(), unknown()).optional(),
@@ -17807,20 +17897,21 @@ const bundleFileResult = object({
17807
17897
  diagnostics: array(diagnostic)
17808
17898
  }).strict();
17809
17899
  const direct = { kind: "direct" };
17810
- const json = (name, schema) => ({
17900
+ const json = (name, schema, acceptsUndefined = false) => ({
17811
17901
  name,
17812
17902
  wire: name,
17813
17903
  source: "json",
17904
+ ...acceptsUndefined ? { acceptsUndefined: true } : {},
17814
17905
  codec: {
17815
17906
  mode: "strict",
17816
17907
  typeSymbol: `dsh-design-studio-dsh#${name}`,
17817
- schema
17908
+ create: () => schema
17818
17909
  }
17819
17910
  });
17820
17911
  const result = (name, schema) => ({
17821
17912
  mode: "strict",
17822
17913
  typeSymbol: `dsh-design-studio-dsh#${name}`,
17823
- schema
17914
+ create: () => schema
17824
17915
  });
17825
17916
  /** The `studioManagement` namespace contribution mounted by the browser adapter. */
17826
17917
  const TYPERT_REMOTE = {
@@ -17850,7 +17941,7 @@ const TYPERT_REMOTE = {
17850
17941
  namespace: "studioManagement",
17851
17942
  method: "readBundleWorkspace",
17852
17943
  invocation: direct,
17853
- parameters: [json("name", string()), json("version", string().optional())],
17944
+ parameters: [json("name", string()), json("version", string().optional(), true)],
17854
17945
  result: result("readBundleWorkspaceResult", bundleWorkspaceResult)
17855
17946
  },
17856
17947
  {
@@ -17862,7 +17953,7 @@ const TYPERT_REMOTE = {
17862
17953
  parameters: [
17863
17954
  json("name", string()),
17864
17955
  json("path", string()),
17865
- json("version", string().optional())
17956
+ json("version", string().optional(), true)
17866
17957
  ],
17867
17958
  result: result("readBundleFileResult", bundleFileResult)
17868
17959
  }
@@ -17891,6 +17982,7 @@ const serverResponseSchema = object({
17891
17982
  }).strict();
17892
17983
  function resolveBase() {
17893
17984
  const location = globalThis.location;
17985
+ if (isDshDesktopLocation(location?.href)) return "dsh-app://app/";
17894
17986
  return location?.origin !== void 0 && location.origin !== "null" ? location.origin : "http://dsh.internal";
17895
17987
  }
17896
17988
  /**
@@ -17930,7 +18022,7 @@ async function callStudioManagement(method, args, doFetch) {
17930
18022
  };
17931
18023
  return {
17932
18024
  ok: true,
17933
- value: descriptor.result.schema.parse(envelope.result.value)
18025
+ value: descriptor.result.create().parse(envelope.result.value)
17934
18026
  };
17935
18027
  }
17936
18028
  /**
@@ -17960,13 +18052,35 @@ function createSameOriginStudioRemote(doFetch = (input, init) => globalThis.fetc
17960
18052
  //#endregion
17961
18053
  //#region src/page-client.tsx
17962
18054
  /** Standalone Design Studio page: thin same-origin RPC over the shared UI. */
18055
+ /** Only Desktop needs a return affordance; locale follows the shared UI's public props. */
18056
+ function DesktopStudioPage({ client }) {
18057
+ const [locale, setLocale] = (0, import_react.useState)(() => (document.documentElement.lang || navigator.language || "zh").toLowerCase().startsWith("en") ? "en" : "zh");
18058
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
18059
+ style: {
18060
+ display: "flex",
18061
+ flexDirection: "column",
18062
+ height: "100%"
18063
+ },
18064
+ children: [renderStudioReturnNavigation(locale === "zh"), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
18065
+ style: {
18066
+ flex: "1 1 auto",
18067
+ minHeight: 0
18068
+ },
18069
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StudioWorkspace, {
18070
+ client,
18071
+ locale,
18072
+ onLocaleChange: setLocale
18073
+ })
18074
+ })]
18075
+ });
18076
+ }
17963
18077
  /** Render the shared workspace over the host /api transport; no DSH client plugin boots. */
17964
18078
  function main() {
17965
18079
  const container = document.getElementById("root");
17966
18080
  if (container === null) throw new Error("design studio page: #root mount point is missing");
17967
18081
  const client = createDshStudioClient(createSameOriginStudioRemote());
17968
18082
  const root = (0, import_client.createRoot)(container);
17969
- root.render(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(StudioWorkspace, { client }));
18083
+ root.render(studioConversationReturnPath() === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StudioWorkspace, { client }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DesktopStudioPage, { client }));
17970
18084
  window.addEventListener("pagehide", () => {
17971
18085
  root.unmount();
17972
18086
  }, { once: true });
@@ -0,0 +1,14 @@
1
+ //#region src/page-path.d.ts
2
+ /** Browser-safe path constants shared by the host route and the launcher. */
3
+ /** Base path owned by the Studio page route. */
4
+ declare const STUDIO_PAGE_BASE = "/design-studio/";
5
+ /** Slash-less route that redirects to the base path. */
6
+ declare const STUDIO_PAGE_PATH = "/design-studio";
7
+ /** Bundle file name served below the base path. */
8
+ declare const STUDIO_PAGE_BUNDLE = "page-client.js";
9
+ /** Recognize only the official Desktop application authority, not a redirect hint. */
10
+ declare function isDshDesktopLocation(href?: string | undefined): boolean;
11
+ /** Desktop returns through the known application root; no caller-controlled redirect. */
12
+ declare function studioConversationReturnPath(href?: string | undefined): '/' | undefined;
13
+ //#endregion
14
+ export { studioConversationReturnPath as a, isDshDesktopLocation as i, STUDIO_PAGE_BUNDLE as n, STUDIO_PAGE_PATH as r, STUDIO_PAGE_BASE as t };
@@ -1,2 +1,2 @@
1
- import { n as STUDIO_PAGE_BUNDLE, r as STUDIO_PAGE_PATH, t as STUDIO_PAGE_BASE } from "./page-path-Nt6gFiV-.js";
2
- export { STUDIO_PAGE_BASE, STUDIO_PAGE_BUNDLE, STUDIO_PAGE_PATH };
1
+ import { a as studioConversationReturnPath, i as isDshDesktopLocation, n as STUDIO_PAGE_BUNDLE, r as STUDIO_PAGE_PATH, t as STUDIO_PAGE_BASE } from "./page-path-wn8e_fid.js";
2
+ export { STUDIO_PAGE_BASE, STUDIO_PAGE_BUNDLE, STUDIO_PAGE_PATH, isDshDesktopLocation, studioConversationReturnPath };
package/lib/page-path.js CHANGED
@@ -6,5 +6,21 @@ const STUDIO_PAGE_BASE = "/design-studio/";
6
6
  const STUDIO_PAGE_PATH = "/design-studio";
7
7
  /** Bundle file name served below the base path. */
8
8
  const STUDIO_PAGE_BUNDLE = "page-client.js";
9
+ /** Recognize only the official Desktop application authority, not a redirect hint. */
10
+ function isDshDesktopLocation(href = globalThis.location?.href) {
11
+ if (href === void 0) return false;
12
+ try {
13
+ const url = new URL(href);
14
+ return url.protocol === "dsh-app:" && url.host === "app" && url.username === "" && url.password === "";
15
+ } catch {
16
+ return false;
17
+ }
18
+ }
19
+ /** Desktop returns through the known application root; no caller-controlled redirect. */
20
+ function studioConversationReturnPath(href = globalThis.location?.href) {
21
+ if (!isDshDesktopLocation(href)) return void 0;
22
+ const { pathname } = new URL(href);
23
+ return pathname === "/design-studio/" || pathname === "/design-studio" ? "/" : void 0;
24
+ }
9
25
  //#endregion
10
- export { STUDIO_PAGE_BASE, STUDIO_PAGE_BUNDLE, STUDIO_PAGE_PATH };
26
+ export { STUDIO_PAGE_BASE, STUDIO_PAGE_BUNDLE, STUDIO_PAGE_PATH, isDshDesktopLocation, studioConversationReturnPath };
package/lib/page-rpc.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { isDshDesktopLocation } from "./page-path.js";
1
2
  import { TYPERT_REMOTE } from "./typert.remote-client.js";
2
3
  import { z } from "zod";
3
4
  //#region src/page-rpc.ts
@@ -22,6 +23,7 @@ const serverResponseSchema = z.object({
22
23
  }).strict();
23
24
  function resolveBase() {
24
25
  const location = globalThis.location;
26
+ if (isDshDesktopLocation(location?.href)) return "dsh-app://app/";
25
27
  return location?.origin !== void 0 && location.origin !== "null" ? location.origin : "http://dsh.internal";
26
28
  }
27
29
  /**
@@ -61,7 +63,7 @@ async function callStudioManagement(method, args, doFetch) {
61
63
  };
62
64
  return {
63
65
  ok: true,
64
- value: descriptor.result.schema.parse(envelope.result.value)
66
+ value: descriptor.result.create().parse(envelope.result.value)
65
67
  };
66
68
  }
67
69
  /**
package/lib/page.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { r as STUDIO_PAGE_PATH, t as STUDIO_PAGE_BASE } from "./page-path-Nt6gFiV-.js";
1
+ import { r as STUDIO_PAGE_PATH, t as STUDIO_PAGE_BASE } from "./page-path-wn8e_fid.js";
2
2
  //#region src/page.d.ts
3
3
  /** Minimal WebServer surface consumed by this plugin. */
4
4
  interface StudioPageWebServer {
@@ -1,5 +1,13 @@
1
1
  //#region src/typert.remote-client.d.ts
2
- /** Runtime descriptor fields consumed opaquely by DSH's Remote registry. */
2
+ /** Strict factory contract; the Host requires a parser, not a validator library. */
3
+ interface StudioStrictCodec {
4
+ readonly mode: 'strict';
5
+ readonly typeSymbol: string;
6
+ readonly create: () => {
7
+ parse(value: unknown): unknown;
8
+ };
9
+ }
10
+ /** Runtime descriptor fields consumed by DSH's Remote registry and page transport. */
3
11
  interface StudioRemoteDescriptor {
4
12
  readonly id: string;
5
13
  readonly service: string;
@@ -9,8 +17,14 @@ interface StudioRemoteDescriptor {
9
17
  readonly kind: 'direct';
10
18
  };
11
19
  readonly scope?: never;
12
- readonly parameters: readonly unknown[];
13
- readonly result: unknown;
20
+ readonly parameters: readonly {
21
+ readonly name: string;
22
+ readonly wire: string;
23
+ readonly source: 'json';
24
+ readonly acceptsUndefined?: true;
25
+ readonly codec: StudioStrictCodec;
26
+ }[];
27
+ readonly result: StudioStrictCodec;
14
28
  }
15
29
  /** Browser/Host contribution without leaking the validator library's types. */
16
30
  interface StudioRemoteContribution {
@@ -20,4 +34,4 @@ interface StudioRemoteContribution {
20
34
  /** The `studioManagement` namespace contribution mounted by the browser adapter. */
21
35
  declare const TYPERT_REMOTE: StudioRemoteContribution;
22
36
  //#endregion
23
- export { StudioRemoteContribution, StudioRemoteDescriptor, TYPERT_REMOTE, TYPERT_REMOTE as default };
37
+ export { StudioRemoteContribution, StudioRemoteDescriptor, StudioStrictCodec, TYPERT_REMOTE, TYPERT_REMOTE as default };
@@ -10,12 +10,20 @@ const diagnostic = z.object({
10
10
  message: z.string(),
11
11
  subject: z.string().optional()
12
12
  }).strict();
13
+ const relationText = z.object({
14
+ zh: z.string(),
15
+ en: z.string()
16
+ }).strict();
13
17
  const kitView = z.object({
14
18
  name: z.string(),
15
- version: z.string()
19
+ version: z.string(),
20
+ description: z.string().optional(),
21
+ displayDescription: relationText.optional()
16
22
  }).strict();
17
23
  const bundleView = pin.extend({
18
24
  description: z.string(),
25
+ title: relationText.optional(),
26
+ displayDescription: relationText.optional(),
19
27
  usedBy: z.array(kitView)
20
28
  }).strict();
21
29
  const workspace = z.object({
@@ -25,16 +33,14 @@ const workspace = z.object({
25
33
  }).strict();
26
34
  const mountView = pin.extend({
27
35
  description: z.string(),
36
+ title: relationText.optional(),
37
+ displayDescription: relationText.optional(),
28
38
  mountedBy: z.array(kitView)
29
39
  }).strict();
30
40
  const resourceView = z.object({
31
41
  path: z.string(),
32
42
  bytes: z.number().int().nonnegative()
33
43
  }).strict();
34
- const relationText = z.object({
35
- zh: z.string(),
36
- en: z.string()
37
- }).strict();
38
44
  const relationView = z.object({
39
45
  type: z.string(),
40
46
  meaning: z.string(),
@@ -64,6 +70,7 @@ const kitWorkspaceView = z.object({
64
70
  name: z.string(),
65
71
  version: z.string(),
66
72
  description: z.string(),
73
+ displayDescription: relationText.optional(),
67
74
  mindsetSource: z.string(),
68
75
  mounts: z.array(mountView),
69
76
  resources: z.array(resourceView),
@@ -90,6 +97,7 @@ const bundleWorkspaceView = z.object({
90
97
  version: z.string(),
91
98
  kit: z.string().optional(),
92
99
  description: z.string(),
100
+ displayDescription: relationText.optional(),
93
101
  files: z.array(bundleFileRef),
94
102
  manifest: z.record(z.string(), z.unknown()).optional(),
95
103
  schema: z.record(z.string(), z.unknown()).optional(),
@@ -109,20 +117,21 @@ const bundleFileResult = z.object({
109
117
  diagnostics: z.array(diagnostic)
110
118
  }).strict();
111
119
  const direct = { kind: "direct" };
112
- const json = (name, schema) => ({
120
+ const json = (name, schema, acceptsUndefined = false) => ({
113
121
  name,
114
122
  wire: name,
115
123
  source: "json",
124
+ ...acceptsUndefined ? { acceptsUndefined: true } : {},
116
125
  codec: {
117
126
  mode: "strict",
118
127
  typeSymbol: `dsh-design-studio-dsh#${name}`,
119
- schema
128
+ create: () => schema
120
129
  }
121
130
  });
122
131
  const result = (name, schema) => ({
123
132
  mode: "strict",
124
133
  typeSymbol: `dsh-design-studio-dsh#${name}`,
125
- schema
134
+ create: () => schema
126
135
  });
127
136
  /** The `studioManagement` namespace contribution mounted by the browser adapter. */
128
137
  const TYPERT_REMOTE = {
@@ -152,7 +161,7 @@ const TYPERT_REMOTE = {
152
161
  namespace: "studioManagement",
153
162
  method: "readBundleWorkspace",
154
163
  invocation: direct,
155
- parameters: [json("name", z.string()), json("version", z.string().optional())],
164
+ parameters: [json("name", z.string()), json("version", z.string().optional(), true)],
156
165
  result: result("readBundleWorkspaceResult", bundleWorkspaceResult)
157
166
  },
158
167
  {
@@ -164,7 +173,7 @@ const TYPERT_REMOTE = {
164
173
  parameters: [
165
174
  json("name", z.string()),
166
175
  json("path", z.string()),
167
- json("version", z.string().optional())
176
+ json("version", z.string().optional(), true)
168
177
  ],
169
178
  result: result("readBundleFileResult", bundleFileResult)
170
179
  }
@@ -2,27 +2,27 @@
2
2
  "schemaVersion": 1,
3
3
  "package": "@yugoo-design/dsh-design-studio-dsh",
4
4
  "scope": "observed-current-dsh-output-and-selected-original-materials",
5
- "sourceArchiveObserved": null,
5
+ "sourceArchiveObserved": "fdc620419b7827987500d6dc3ad8ae1504a5970942827868c7a823bc543822c7",
6
6
  "outputSha256": {
7
- "lib/client-adapter.js": "87f090f76c404668cbe5811ac875a9585131cb0c0332f2ad75f0b194b5aadb36",
8
- "lib/client.js": "1969fe0923e047b360447d78493c4e3759740fe5a5b4a4c5bedbe0f9c6115c3b",
7
+ "lib/client-adapter.js": "84c342631d8aefebad8a316a259c43f62ceb67c66c629b69b29c5c7fbff97836",
8
+ "lib/client.js": "d3e35a45aafee5140176c1e519c8210b0e5a0aee47fa8ceb654046b33478091b",
9
9
  "lib/index.js": "4f85243fed85ecefbc894bc14bf33d598afae7488489cc37c3a289df0774f23f",
10
- "lib/page-client.js": "6f7a567968352d9037c109d35823b1140704ef2cf6a342badd331e96a0f29abf",
11
- "lib/page-path.js": "731eb601ffd7bff9c47511ebd3b5b03fa44270919605164588511d6e6e49b44f",
12
- "lib/page-rpc.js": "32f9e7e6736df2910bcb140878dec6ce9a977f9080028d21bb221d02b2f1ed97",
10
+ "lib/page-client.js": "c0d1407b10df0ebb18f550341dd413c22eee9e3224353f8cdb0dd932b4ae9242",
11
+ "lib/page-path.js": "30b04bda77901e33e2d627d525cb19c9f4c103798234f1adc153a34e3608ccd1",
12
+ "lib/page-rpc.js": "a2e0f435924148febbffa560a162545de6c29a2bfa455be3ca4c655052b06fc4",
13
13
  "lib/page.js": "c0fbd159525dba9223dcc147fa6b4a6ad7a7b59005950d63565346da1ee49939",
14
14
  "lib/typert.host.js": "ef9f99c997c98b9ce63ee4f2aaa2efba0bc6a609a5b6b51eccb578f2a5f3a715",
15
- "lib/typert.remote-client.js": "2f2d11f64f1780a7083696f95d2b019db6c1e7950a120b0a9fc6edf78522bf37"
15
+ "lib/typert.remote-client.js": "881e503e2d9239408b852d9c5fa97a217b4aa3234176a26c771490e07c6f108d"
16
16
  },
17
17
  "normalBuildMaps": [
18
18
  {
19
19
  "output": "lib/client.js",
20
- "mapSha256": "1db724db4faebfa3a87d4c3ec7ce38dc22a2bc5700baf7d3ac4a0ba3bdfe541a",
20
+ "mapSha256": "42c8cf2de38fc57b645af4ee6c87fbb79bc50e5f71c35ec0f174199765b85bfc",
21
21
  "sourceCount": 3,
22
- "normalOutputSha256": "2b30aa64a6e40f4a6c2c7005161922f8c2f9f4442ae08170d0230dfe7037c4cf",
23
- "packedOutputSha256": "1969fe0923e047b360447d78493c4e3759740fe5a5b4a4c5bedbe0f9c6115c3b",
22
+ "normalOutputSha256": "eb3f9c1f36fd3be55641a251d44041519ee99fa8d167776341eb3f28e49a9efb",
23
+ "packedOutputSha256": "d3e35a45aafee5140176c1e519c8210b0e5a0aee47fa8ceb654046b33478091b",
24
24
  "actualArchiveOutputBindingVerified": false,
25
- "binding": "Current normal-build output projected by existing projectDistributionCode; archive output binding is pending actual pack verification."
25
+ "binding": "Fixed normal output adapted by existing projectDistributionCode and byte-verified against reviewed staging; no new archive has been packed or observed. Root must verify actual archive members separately."
26
26
  }
27
27
  ],
28
28
  "components": [
@@ -103,12 +103,15 @@
103
103
  },
104
104
  "externalPeers": {
105
105
  "@deepseek-ai/cordis": "^4.0.1",
106
- "@deepseek-ai/dsh-client-locale": ">=0.1.1-rc.2 <0.2.0 || 0.1.2-rc.1 || 0.2.0-rc.2",
107
- "@deepseek-ai/dsh-client-ui-settings": ">=0.1.0-rc.5 <0.2.0 || 0.1.2-rc.1 || 0.2.0-rc.2",
108
- "@deepseek-ai/dsh-client-ui-slots": ">=0.1.0-rc.5 <0.2.0 || 0.1.2-rc.1 || 0.2.0-rc.2",
109
- "@deepseek-ai/dsh-fs": ">=0.1.0-rc.5 <0.2.0 || 0.1.2-rc.1 || 0.2.0-rc.2",
110
- "@deepseek-ai/dsh-host-webserver": ">=0.1.1-rc.2 <0.2.0 || 0.1.2-rc.1 || 0.2.0-rc.2",
111
- "@deepseek-ai/dsh-typert-protocol": ">=0.1.0-rc.5 <0.2.0 || 0.1.2-rc.1 || 0.2.0-rc.2",
106
+ "@deepseek-ai/dsh-client-locale": "0.2.0-rc.2",
107
+ "@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.2",
108
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.2",
109
+ "@deepseek-ai/dsh-fs": "0.2.0-rc.2",
110
+ "@deepseek-ai/dsh-host-webserver": "0.2.0-rc.2",
111
+ "@deepseek-ai/dsh-typert-protocol": "0.2.0-rc.2",
112
+ "@yugoo-design/dsh-design-core": "0.1.0-beta.3",
113
+ "@yugoo-design/dsh-design-studio": "0.1.0-beta.3",
114
+ "@yugoo-design/dsh-design-studio-ui": "0.1.0-beta.3",
112
115
  "react": "^18.2.0",
113
116
  "react-dom": "^18.2.0"
114
117
  },
@@ -122,7 +125,8 @@
122
125
  "This component list is scoped to retained maps whose output was compared to actual adapted archive bytes, and emitted source-region IDs; no complete coverage claim for generated/unmapped code.",
123
126
  "External npm dependencies and peer host services are separate artifacts, even where other modules from that package are embedded.",
124
127
  "Shared Radix/upstream attribution records keep their original historical-source limitations.",
125
- "Existing embedded/font/native source obligations and rendering checks remain distinct from delivery of original license text."
128
+ "Existing embedded/font/native source obligations and rendering checks remain distinct from delivery of original license text.",
129
+ "This refreshed observation covers the fixed 1b304cc staging only; no new archive, installed Desktop round trip, complete bundled inventory or license acceptance is inferred."
126
130
  ],
127
131
  "completeBundledInventoryVerified": false,
128
132
  "releaseLicenseAcceptance": false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yugoo-design/dsh-design-studio-dsh",
3
- "version": "0.1.0-beta.1",
3
+ "version": "0.1.0-beta.3",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "description": "DSH lifecycle, Remote, source, and Settings adapter for the read-only Design Studio.",
@@ -46,15 +46,15 @@
46
46
  },
47
47
  "peerDependencies": {
48
48
  "@deepseek-ai/cordis": "^4.0.1",
49
- "@deepseek-ai/dsh-client-locale": ">=0.1.1-rc.2 <0.2.0 || 0.1.2-rc.1 || 0.2.0-rc.2",
50
- "@deepseek-ai/dsh-client-ui-settings": ">=0.1.0-rc.5 <0.2.0 || 0.1.2-rc.1 || 0.2.0-rc.2",
51
- "@deepseek-ai/dsh-client-ui-slots": ">=0.1.0-rc.5 <0.2.0 || 0.1.2-rc.1 || 0.2.0-rc.2",
52
- "@deepseek-ai/dsh-fs": ">=0.1.0-rc.5 <0.2.0 || 0.1.2-rc.1 || 0.2.0-rc.2",
53
- "@deepseek-ai/dsh-host-webserver": ">=0.1.1-rc.2 <0.2.0 || 0.1.2-rc.1 || 0.2.0-rc.2",
54
- "@deepseek-ai/dsh-typert-protocol": ">=0.1.0-rc.5 <0.2.0 || 0.1.2-rc.1 || 0.2.0-rc.2",
55
- "@yugoo-design/dsh-design-core": "0.1.0-beta.1",
56
- "@yugoo-design/dsh-design-studio": "0.1.0-beta.1",
57
- "@yugoo-design/dsh-design-studio-ui": "0.1.0-beta.1",
49
+ "@deepseek-ai/dsh-client-locale": "0.2.0-rc.2",
50
+ "@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.2",
51
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.2",
52
+ "@deepseek-ai/dsh-fs": "0.2.0-rc.2",
53
+ "@deepseek-ai/dsh-host-webserver": "0.2.0-rc.2",
54
+ "@deepseek-ai/dsh-typert-protocol": "0.2.0-rc.2",
55
+ "@yugoo-design/dsh-design-core": "0.1.0-beta.3",
56
+ "@yugoo-design/dsh-design-studio": "0.1.0-beta.3",
57
+ "@yugoo-design/dsh-design-studio-ui": "0.1.0-beta.3",
58
58
  "react": "^18.2.0",
59
59
  "react-dom": "^18.2.0"
60
60
  },
@@ -1,10 +0,0 @@
1
- //#region src/page-path.d.ts
2
- /** Browser-safe path constants shared by the host route and the launcher. */
3
- /** Base path owned by the Studio page route. */
4
- declare const STUDIO_PAGE_BASE = "/design-studio/";
5
- /** Slash-less route that redirects to the base path. */
6
- declare const STUDIO_PAGE_PATH = "/design-studio";
7
- /** Bundle file name served below the base path. */
8
- declare const STUDIO_PAGE_BUNDLE = "page-client.js";
9
- //#endregion
10
- export { STUDIO_PAGE_BUNDLE as n, STUDIO_PAGE_PATH as r, STUDIO_PAGE_BASE as t };