dsh-mobile 0.3.3 → 0.3.5

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/lib/index.d.mts CHANGED
@@ -312,7 +312,7 @@ declare function parseGatewayConfig(raw: unknown): ResolvedGatewayConfig;
312
312
  //#endregion
313
313
  //#region src/compatibility.d.ts
314
314
  /** DeepSeek Harness prereleases verified by this plugin release. */
315
- declare const SUPPORTED_DSH_VERSIONS: readonly ["0.1.0-rc.5", "0.1.0-rc.6", "0.1.0-rc.7", "0.1.1-rc.2", "0.1.2-alpha.1"];
315
+ declare const SUPPORTED_DSH_VERSIONS: readonly ["0.1.0-rc.5", "0.1.0-rc.6", "0.1.0-rc.7", "0.1.1-rc.2", "0.1.2-alpha.1", "0.1.2-alpha.2"];
316
316
  /**
317
317
  * Reject an unverified DeepSeek Harness Host before opening the LAN listener.
318
318
  * @param version - Version reported by the installed DSH WebServer package.
package/lib/index.mjs CHANGED
@@ -710,7 +710,8 @@ const SUPPORTED_DSH_VERSIONS = Object.freeze([
710
710
  "0.1.0-rc.6",
711
711
  "0.1.0-rc.7",
712
712
  "0.1.1-rc.2",
713
- "0.1.2-alpha.1"
713
+ "0.1.2-alpha.1",
714
+ "0.1.2-alpha.2"
714
715
  ]);
715
716
  /**
716
717
  * Reject an unverified DeepSeek Harness Host before opening the LAN listener.
@@ -2049,6 +2050,8 @@ const RUNTIME_MODULE = "@deepseek-ai/dsh-client-runtime";
2049
2050
  const RENDERER_MODULE = "@deepseek-ai/dsh-client-ui-renderer";
2050
2051
  const SIDEBAR_MODULE = "@deepseek-ai/dsh-client-ui-sidebar";
2051
2052
  const SETTINGS_MODULE = "@deepseek-ai/dsh-client-ui-settings";
2053
+ const API_GATEWAY_MODULE = "@deepseek-ai/dsh-api-gateway";
2054
+ const API_REMOTES_MODULE = "@deepseek-ai/dsh-api-remotes";
2052
2055
  const MOBILE_LAYOUT_DEPENDENCY_PROFILES = Object.freeze([Object.freeze({
2053
2056
  slots: RUNTIME_MODULE,
2054
2057
  dependencies: Object.freeze([RUNTIME_MODULE, "@deepseek-ai/dsh-client-ui-theme"])
@@ -2062,6 +2065,7 @@ const MOBILE_LAYOUT_DEPENDENCY_PROFILES = Object.freeze([Object.freeze({
2062
2065
  ])
2063
2066
  })]);
2064
2067
  const MOBILE_CSRF_FETCH_BOOTSTRAP = `(()=>{const nativeFetch=window.fetch.bind(window);window.fetch=(input,init)=>{const source=input instanceof Request?input:undefined;const method=String(init?.method??source?.method??'GET').toUpperCase();if(method==='GET'||method==='HEAD')return nativeFetch(input,init);const raw=typeof input==='string'?input:input instanceof URL?input.href:source?.url;if(raw===undefined||new URL(raw,location.href).origin!==location.origin)return nativeFetch(input,init);const headers=new Headers(init?.headers??source?.headers);if(!headers.has(${JSON.stringify(CSRF_HEADER)})){const prefix=${JSON.stringify(`${CSRF_COOKIE}=`)};const token=document.cookie.split(';').map(value=>value.trim()).find(value=>value.startsWith(prefix))?.slice(prefix.length);if(token!==undefined)headers.set(${JSON.stringify(CSRF_HEADER)},token)}return nativeFetch(input,{...init,headers})};})();`;
2068
+ const MOBILE_AUTHENTICATED_TRANSPORT_BOOTSTRAP = `(()=>{if(window.__DSH_TRANSPORT__!==undefined)throw new Error('DSH Mobile cannot replace an existing transport override');window.__DSH_TRANSPORT__={fetch:(input,init)=>window.fetch(input,init),ownsHost:true}})();`;
2065
2069
  const PAIR_PAGE = `<!doctype html>
2066
2070
  <html lang="en">
2067
2071
  <meta charset="utf-8">
@@ -2096,12 +2100,21 @@ function ensureMobileViewport(html) {
2096
2100
  function orderAuthenticatedSettings(entries, slotsProvider) {
2097
2101
  const mobile = entries.filter((entry) => entry !== null && typeof entry === "object" && entry.id === MOBILE_CLIENT_MODULE);
2098
2102
  const settings = entries.filter((entry) => entry !== null && typeof entry === "object" && entry.id === SETTINGS_MODULE);
2099
- if (mobile.length === 0 || settings.length === 0) return;
2103
+ if (mobile.length === 0 || settings.length === 0) return false;
2100
2104
  if (mobile.length !== 1 || settings.length !== 1) throw new Error("upstream DSH mobile settings graph is ambiguous");
2101
2105
  if (!Array.isArray(mobile[0]?.inject) || !mobile[0].inject.includes(CONNECTION_MODULE) || !mobile[0].inject.includes(SIDEBAR_MODULE)) throw new Error("dsh-mobile client has unsupported dependencies");
2102
- if (!Array.isArray(settings[0]?.inject) || !settings[0].inject.includes(CONNECTION_MODULE)) throw new Error("upstream DSH settings module has unsupported dependencies");
2106
+ if (!Array.isArray(settings[0]?.inject)) throw new Error("upstream DSH settings module has unsupported dependencies");
2107
+ const remoteSettings = !settings[0].inject.includes(CONNECTION_MODULE);
2108
+ if (remoteSettings) {
2109
+ if (!settings[0].inject.includes(API_REMOTES_MODULE) || slotsProvider !== RENDERER_MODULE) throw new Error("upstream DSH settings module has unsupported dependencies");
2110
+ const remotes = entries.filter((entry) => entry !== null && typeof entry === "object" && entry.id === API_REMOTES_MODULE);
2111
+ const gateway = entries.filter((entry) => entry !== null && typeof entry === "object" && entry.id === API_GATEWAY_MODULE);
2112
+ if (remotes.length !== 1 || !Array.isArray(remotes[0]?.inject) || !remotes[0].inject.includes(API_GATEWAY_MODULE) || gateway.length !== 1 || !Array.isArray(gateway[0]?.inject) || !gateway[0].inject.includes(CONNECTION_MODULE)) throw new Error("upstream DSH settings Remote graph has unsupported dependencies");
2113
+ if (!gateway[0].inject.includes(MOBILE_CLIENT_MODULE)) gateway[0].inject = [...gateway[0].inject, MOBILE_CLIENT_MODULE];
2114
+ }
2103
2115
  mobile[0].inject = [CONNECTION_MODULE, slotsProvider];
2104
2116
  if (!settings[0].inject.includes(MOBILE_CLIENT_MODULE)) settings[0].inject = [...settings[0].inject, MOBILE_CLIENT_MODULE];
2117
+ return remoteSettings;
2105
2118
  }
2106
2119
  function revisionedMobileBatchPath(entries) {
2107
2120
  const key = createHash("sha256").update(DSH_MOBILE_VERSION).update(JSON.stringify(entries)).digest("hex");
@@ -2128,7 +2141,7 @@ function rewriteMobileIndexWithBatch(html) {
2128
2141
  if (dependencyProfile === void 0) throw new Error("upstream DSH layout module has unsupported dependencies");
2129
2142
  layout[0].url = MOBILE_LAYOUT_PATH;
2130
2143
  layout[0].rev = `dsh-mobile-layout-${DSH_MOBILE_VERSION}`;
2131
- orderAuthenticatedSettings(entries, dependencyProfile.slots);
2144
+ const remoteSettings = orderAuthenticatedSettings(entries, dependencyProfile.slots);
2132
2145
  let mobileBatch;
2133
2146
  if (parsed.batches !== void 0) {
2134
2147
  if (!Array.isArray(parsed.batches)) throw new Error("upstream DSH boot manifest batches are malformed");
@@ -2163,7 +2176,7 @@ function rewriteMobileIndexWithBatch(html) {
2163
2176
  batches
2164
2177
  })).digest("hex").slice(0, 16);
2165
2178
  }
2166
- const replacement = `${MOBILE_CSRF_FETCH_BOOTSTRAP}window.__DSH_MOBILE_FRONTEND__="dedicated";${assignment[0]}${JSON.stringify(parsed)};`;
2179
+ const replacement = `${remoteSettings ? MOBILE_AUTHENTICATED_TRANSPORT_BOOTSTRAP : ""}${MOBILE_CSRF_FETCH_BOOTSTRAP}window.__DSH_MOBILE_FRONTEND__="dedicated";${assignment[0]}${JSON.stringify(parsed)};`;
2167
2180
  return Object.freeze({
2168
2181
  html: ensureMobileViewport(`${html.slice(0, start)}${replacement}${html.slice(scriptEnd)}`),
2169
2182
  ...mobileBatch === void 0 ? {} : { batch: mobileBatch }
@@ -3767,12 +3780,15 @@ var MobileAccessGateway = class {
3767
3780
  };
3768
3781
  const data = (chunk) => {
3769
3782
  buffer = Buffer.concat([buffer, chunk]);
3770
- if (buffer.length > MAX_HEADER_BYTES) {
3783
+ const end = buffer.indexOf("\r\n\r\n");
3784
+ if (end < 0) {
3785
+ if (buffer.length >= MAX_HEADER_BYTES) failed(/* @__PURE__ */ new Error("upstream WebSocket headers are too large"));
3786
+ return;
3787
+ }
3788
+ if (end + 4 > MAX_HEADER_BYTES) {
3771
3789
  failed(/* @__PURE__ */ new Error("upstream WebSocket headers are too large"));
3772
3790
  return;
3773
3791
  }
3774
- const end = buffer.indexOf("\r\n\r\n");
3775
- if (end < 0) return;
3776
3792
  cleanup();
3777
3793
  const lines = buffer.subarray(0, end).toString("latin1").split("\r\n");
3778
3794
  if (lines.shift() !== "HTTP/1.1 101 Switching Protocols") {
@@ -6685,6 +6701,14 @@ function launchedProfileName(argv) {
6685
6701
  }
6686
6702
  return "web";
6687
6703
  }
6704
+ /** Resolve the launcher-owned Desktop profile, or the CLI profile outside Desktop. */
6705
+ function releaseProfileDirectory(ctx, dshHome, argv) {
6706
+ const desktopProfiles = ctx.get("desktopProfiles");
6707
+ const desktopDirectory = desktopProfiles?.current?.dir;
6708
+ if (typeof desktopDirectory === "string" && isAbsolute(desktopDirectory)) return desktopDirectory;
6709
+ if (desktopProfiles !== void 0 || ctx.get("desktopRuntime") !== void 0) return void 0;
6710
+ return join(dshHome, "profiles", launchedProfileName(argv));
6711
+ }
6688
6712
  async function profileDependencySpec(profileDirectory) {
6689
6713
  try {
6690
6714
  const value = JSON.parse(await readFile(join(profileDirectory, "package.json"), "utf8")).dependencies?.[PACKAGE_NAME];
@@ -6930,7 +6954,7 @@ var PluginReleaseManager = class {
6930
6954
  /** Read cached release metadata and suppress external lookup failures. */
6931
6955
  async status(force = false) {
6932
6956
  if (!force && this.cache !== void 0 && this.cache.expiresAt > this.now()) return this.cache.status;
6933
- const updateSupported = isRegistryPluginSpec(await profileDependencySpec(this.profileDirectory));
6957
+ const updateSupported = isRegistryPluginSpec(this.profileDirectory === void 0 ? void 0 : await profileDependencySpec(this.profileDirectory));
6934
6958
  const [npmResult, androidResult] = await Promise.allSettled([fetchNpmVersion(this.fetcher), fetchAndroidVersion(this.fetcher)]);
6935
6959
  const latestVersion = npmResult.status === "fulfilled" ? npmResult.value : void 0;
6936
6960
  const androidVersion = androidResult.status === "fulfilled" ? androidResult.value : void 0;
@@ -6960,11 +6984,13 @@ var PluginReleaseManager = class {
6960
6984
  }
6961
6985
  }
6962
6986
  async updateOnce() {
6987
+ const profileDirectory = this.profileDirectory;
6988
+ if (profileDirectory === void 0) throw new Error("plugin_update_unsupported");
6963
6989
  const status = await this.status(true);
6964
6990
  if (!status.updateSupported) throw new Error("plugin_update_unsupported");
6965
6991
  if (!status.updateAvailable || status.latestVersion === void 0) throw new Error("plugin_update_unavailable");
6966
- await this.runner(this.profileDirectory, status.latestVersion);
6967
- const installed = await this.installedVersionReader(this.profileDirectory);
6992
+ await this.runner(profileDirectory, status.latestVersion);
6993
+ const installed = await this.installedVersionReader(profileDirectory);
6968
6994
  if (installed !== status.latestVersion) throw new Error("plugin_update_failed");
6969
6995
  this.cache = void 0;
6970
6996
  return Object.freeze({
@@ -7358,8 +7384,7 @@ async function apply(ctx, config) {
7358
7384
  const stateDirectory = dirname(template.stateFile);
7359
7385
  const remoteDirectory = join(stateDirectory, "remote");
7360
7386
  const configuredDshHome = process.env.DSH_HOME?.trim();
7361
- const dshHome = configuredDshHome === void 0 || configuredDshHome === "" ? dirname(stateDirectory) : resolve(configuredDshHome);
7362
- const releaseManager = new PluginReleaseManager({ profileDirectory: join(dshHome, "profiles", launchedProfileName(process.argv.slice(2))) });
7387
+ const releaseManager = new PluginReleaseManager({ profileDirectory: releaseProfileDirectory(ctx, configuredDshHome === void 0 || configuredDshHome === "" ? dirname(stateDirectory) : resolve(configuredDshHome), process.argv.slice(2)) });
7363
7388
  const remoteProviderStore = new JsonRemoteProviderStore(join(remoteDirectory, "provider.json"), configuredRemoteProvider(process.env));
7364
7389
  const initialRemoteProvider = (await remoteProviderStore.load()).provider;
7365
7390
  const cpolarComponent = new CpolarComponentManager({ stateDirectory });