@senguoyun/dsh-arkme 0.1.73 → 0.1.75

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.
Files changed (143) hide show
  1. package/docs/desktop-screenshot.md +75 -28
  2. package/lib/bundle-runtime.js +1 -1
  3. package/lib/client.js +3489 -3552
  4. package/lib/client.js.map +1 -1
  5. package/lib/extension-profile-restart-helper.js +5 -5
  6. package/lib/harness-model-client.js +86 -4
  7. package/lib/harness-native-selection-client.js +62 -0
  8. package/lib/harness-session-client.js +109 -6
  9. package/lib/harness-sidebar-client.js +2055 -6
  10. package/lib/index.js +4501 -1544
  11. package/lib/{install-store-bnyQDtYt.js → install-store-CAljxSo2.js} +2 -2
  12. package/lib/persistent-extension.js +1 -1
  13. package/lib/{plugin-updater-helper-Ny1szQA0.js → plugin-updater-helper-BWIKYugE.js} +5 -5
  14. package/lib/{plugin-updater-helper-D43MAnTY.js → plugin-updater-helper-DVcpMGBt.js} +1 -1
  15. package/lib/plugin-updater-helper.js +1 -1
  16. package/lib/{profile-bundle-policy-DLXDyohJ.js → profile-bundle-policy-Cwi2iuHi.js} +3 -3
  17. package/lib/sdk.js +62 -0
  18. package/lib/types/client/ArkmeArkoSurface.d.ts +31 -4
  19. package/lib/types/client/ArkmeArkoSurface.d.ts.map +1 -1
  20. package/lib/types/client/ArkmeComposerScreenshotButton.d.ts.map +1 -1
  21. package/lib/types/client/ArkmePersistentShell.d.ts.map +1 -1
  22. package/lib/types/client/ArkmeScreenshotCropDialog.d.ts +2 -2
  23. package/lib/types/client/ArkmeScreenshotCropDialog.d.ts.map +1 -1
  24. package/lib/types/client/ArkmeScreenshotEditor.d.ts +15 -0
  25. package/lib/types/client/ArkmeScreenshotEditor.d.ts.map +1 -0
  26. package/lib/types/client/ArkmeScreenshotShortcutSetting.d.ts +2 -0
  27. package/lib/types/client/ArkmeScreenshotShortcutSetting.d.ts.map +1 -0
  28. package/lib/types/client/ArkmeScreenshotTooltip.d.ts +8 -0
  29. package/lib/types/client/ArkmeScreenshotTooltip.d.ts.map +1 -0
  30. package/lib/types/client/ArkmeScreenshotWindow.d.ts +2 -0
  31. package/lib/types/client/ArkmeScreenshotWindow.d.ts.map +1 -0
  32. package/lib/types/client/ArkmeSettingsSurface.d.ts.map +1 -1
  33. package/lib/types/client/ArkoModelMenu.d.ts +10 -0
  34. package/lib/types/client/ArkoModelMenu.d.ts.map +1 -0
  35. package/lib/types/client/DeepSeekHarnessSurface.d.ts +4 -2
  36. package/lib/types/client/DeepSeekHarnessSurface.d.ts.map +1 -1
  37. package/lib/types/client/arko-model-cache.d.ts +21 -0
  38. package/lib/types/client/arko-model-cache.d.ts.map +1 -0
  39. package/lib/types/client/harness-account-sessions.d.ts +68 -0
  40. package/lib/types/client/harness-account-sessions.d.ts.map +1 -0
  41. package/lib/types/client/harness-model-client.d.ts.map +1 -1
  42. package/lib/types/client/harness-native-navigation.d.ts +12 -0
  43. package/lib/types/client/harness-native-navigation.d.ts.map +1 -0
  44. package/lib/types/client/harness-session-client.d.ts +17 -1
  45. package/lib/types/client/harness-session-client.d.ts.map +1 -1
  46. package/lib/types/client/harness-session-dropdown.d.ts.map +1 -1
  47. package/lib/types/client/harness-session-menu-bridge.d.ts +1 -0
  48. package/lib/types/client/harness-session-menu-bridge.d.ts.map +1 -1
  49. package/lib/types/client/harness-session-origin.d.ts +8 -0
  50. package/lib/types/client/harness-session-origin.d.ts.map +1 -0
  51. package/lib/types/client/harness-sidebar-client.d.ts.map +1 -1
  52. package/lib/types/client/index.d.ts.map +1 -1
  53. package/lib/types/client/native-screenshot.d.ts +25 -0
  54. package/lib/types/client/native-screenshot.d.ts.map +1 -0
  55. package/lib/types/client/screenshot-editor-icons.d.ts +6 -0
  56. package/lib/types/client/screenshot-editor-icons.d.ts.map +1 -0
  57. package/lib/types/client/screenshot-editor-model.d.ts +40 -0
  58. package/lib/types/client/screenshot-editor-model.d.ts.map +1 -0
  59. package/lib/types/client/screenshot-editor-render.d.ts +4 -0
  60. package/lib/types/client/screenshot-editor-render.d.ts.map +1 -0
  61. package/lib/types/client/screenshot-shortcut.d.ts +17 -0
  62. package/lib/types/client/screenshot-shortcut.d.ts.map +1 -0
  63. package/lib/types/dsh-remote/account-session-observer.d.ts +9 -0
  64. package/lib/types/dsh-remote/account-session-observer.d.ts.map +1 -0
  65. package/lib/types/dsh-remote/account-session-tools.d.ts +3 -0
  66. package/lib/types/dsh-remote/account-session-tools.d.ts.map +1 -0
  67. package/lib/types/dsh-remote/account-session-types.d.ts +71 -0
  68. package/lib/types/dsh-remote/account-session-types.d.ts.map +1 -0
  69. package/lib/types/dsh-remote/account-sessions.d.ts +36 -0
  70. package/lib/types/dsh-remote/account-sessions.d.ts.map +1 -0
  71. package/lib/types/dsh-remote/api-proxy-adapter.d.ts +28 -0
  72. package/lib/types/dsh-remote/api-proxy-adapter.d.ts.map +1 -1
  73. package/lib/types/dsh-remote/channel-manager.d.ts +3 -0
  74. package/lib/types/dsh-remote/channel-manager.d.ts.map +1 -1
  75. package/lib/types/dsh-remote/cloud-native-transport.d.ts +22 -0
  76. package/lib/types/dsh-remote/cloud-native-transport.d.ts.map +1 -0
  77. package/lib/types/dsh-remote/cloud-turn-history.d.ts +21 -0
  78. package/lib/types/dsh-remote/cloud-turn-history.d.ts.map +1 -0
  79. package/lib/types/dsh-remote/connection-diagnostics.d.ts +5 -0
  80. package/lib/types/dsh-remote/connection-diagnostics.d.ts.map +1 -1
  81. package/lib/types/dsh-remote/control-plane.d.ts +1 -0
  82. package/lib/types/dsh-remote/control-plane.d.ts.map +1 -1
  83. package/lib/types/dsh-remote/desktop-session-presence.d.ts +4 -1
  84. package/lib/types/dsh-remote/desktop-session-presence.d.ts.map +1 -1
  85. package/lib/types/dsh-remote/gateway-api.d.ts.map +1 -1
  86. package/lib/types/dsh-remote/host.d.ts +7 -1
  87. package/lib/types/dsh-remote/host.d.ts.map +1 -1
  88. package/lib/types/dsh-remote/native-history-cache.d.ts +12 -0
  89. package/lib/types/dsh-remote/native-history-cache.d.ts.map +1 -0
  90. package/lib/types/dsh-remote/native-history.d.ts +18 -0
  91. package/lib/types/dsh-remote/native-history.d.ts.map +1 -0
  92. package/lib/types/dsh-remote/native-socket.d.ts +17 -0
  93. package/lib/types/dsh-remote/native-socket.d.ts.map +1 -0
  94. package/lib/types/dsh-remote/native-transport.d.ts +29 -0
  95. package/lib/types/dsh-remote/native-transport.d.ts.map +1 -0
  96. package/lib/types/dsh-remote/protocol-v1.d.ts.map +1 -1
  97. package/lib/types/dsh-remote/realtime-transport.d.ts +3 -0
  98. package/lib/types/dsh-remote/realtime-transport.d.ts.map +1 -1
  99. package/lib/types/dsh-remote/runtime-secret-broker.d.ts +1 -0
  100. package/lib/types/dsh-remote/runtime-secret-broker.d.ts.map +1 -1
  101. package/lib/types/dsh-remote/transport-fragment.d.ts +5 -0
  102. package/lib/types/dsh-remote/transport-fragment.d.ts.map +1 -1
  103. package/lib/types/dsh-remote/turn-projector.d.ts +2 -1
  104. package/lib/types/dsh-remote/turn-projector.d.ts.map +1 -1
  105. package/lib/types/dsh-remote/turn-upload-outbox.d.ts +6 -3
  106. package/lib/types/dsh-remote/turn-upload-outbox.d.ts.map +1 -1
  107. package/lib/types/dsh-remote/types.d.ts +6 -3
  108. package/lib/types/dsh-remote/types.d.ts.map +1 -1
  109. package/lib/types/harness-embed-route.d.ts +0 -1
  110. package/lib/types/harness-embed-route.d.ts.map +1 -1
  111. package/lib/types/harness-native-transport-script.d.ts +11 -0
  112. package/lib/types/harness-native-transport-script.d.ts.map +1 -0
  113. package/lib/types/harness-session-restore-script.d.ts +1 -1
  114. package/lib/types/harness-session-restore-script.d.ts.map +1 -1
  115. package/lib/types/host-api.d.ts +3 -1
  116. package/lib/types/host-api.d.ts.map +1 -1
  117. package/lib/types/index.d.ts.map +1 -1
  118. package/lib/types/sdk/index.d.ts +34 -0
  119. package/lib/types/sdk/index.d.ts.map +1 -1
  120. package/lib/types/types.d.ts +2 -1
  121. package/lib/types/types.d.ts.map +1 -1
  122. package/package.json +6 -5
  123. package/lib/arko-native-client.js +0 -6079
  124. package/lib/types/client/ArkmeArkoPanel.d.ts +0 -5
  125. package/lib/types/client/ArkmeArkoPanel.d.ts.map +0 -1
  126. package/lib/types/client/ArkoNativeSurface.d.ts +0 -27
  127. package/lib/types/client/ArkoNativeSurface.d.ts.map +0 -1
  128. package/lib/types/client/arko-conversation-contract.d.ts +0 -47
  129. package/lib/types/client/arko-conversation-contract.d.ts.map +0 -1
  130. package/lib/types/client/arko-native-client.d.ts +0 -19
  131. package/lib/types/client/arko-native-client.d.ts.map +0 -1
  132. package/lib/types/client/arko-native-composer.d.ts +0 -31
  133. package/lib/types/client/arko-native-composer.d.ts.map +0 -1
  134. package/lib/types/client/arko-native-emoji-picker.d.ts +0 -17
  135. package/lib/types/client/arko-native-emoji-picker.d.ts.map +0 -1
  136. package/lib/types/client/arko-native-frame.d.ts +0 -3
  137. package/lib/types/client/arko-native-frame.d.ts.map +0 -1
  138. package/lib/types/client/arko-native-transport.d.ts +0 -20
  139. package/lib/types/client/arko-native-transport.d.ts.map +0 -1
  140. package/lib/types/client/useArkoConversationController.d.ts +0 -57
  141. package/lib/types/client/useArkoConversationController.d.ts.map +0 -1
  142. package/lib/{bundle-runtime-CE73h3vS.js → bundle-runtime-QUG0eHSZ.js} +1 -1
  143. package/lib/{persistent-runtime-Cb8xQ4w0.js → persistent-runtime-oMlB7XX_.js} +6 -6
@@ -1,9 +1,9 @@
1
- import { i as prepareProfilePackageManager, r as localExtensionPnpmArgs, t as applyArkmeProfileBundlePolicy } from "./profile-bundle-policy-DLXDyohJ.js";
2
- import { t as ArkmeExtensionInstallStore } from "./install-store-bnyQDtYt.js";
1
+ import { i as prepareProfilePackageManager, r as localExtensionPnpmArgs, t as applyArkmeProfileBundlePolicy } from "./profile-bundle-policy-Cwi2iuHi.js";
2
+ import { t as ArkmeExtensionInstallStore } from "./install-store-CAljxSo2.js";
3
3
  import { closeSync, openSync } from "node:fs";
4
- import { readFile, rm, unlink } from "node:fs/promises";
5
- import { spawn, spawnSync } from "node:child_process";
6
4
  import { join, relative, resolve } from "node:path";
5
+ import { spawn, spawnSync } from "node:child_process";
6
+ import { readFile, rm, unlink } from "node:fs/promises";
7
7
  import { fileURLToPath } from "node:url";
8
8
  //#region src/extensions/profile-restart-helper.ts
9
9
  const PARENT_EXIT_TIMEOUT_MS = 2e4;
@@ -224,7 +224,7 @@ async function main() {
224
224
  if (planPath === void 0) throw new Error("extension restart plan path is required");
225
225
  const rawPlan = JSON.parse(await readFile(planPath, "utf8"));
226
226
  if (managed && isPluginUpdateRestartPlan(rawPlan)) {
227
- const pluginUpdate = await import("./plugin-updater-helper-D43MAnTY.js");
227
+ const pluginUpdate = await import("./plugin-updater-helper-DVcpMGBt.js");
228
228
  if (mode === "--managed-finalize") {
229
229
  const healthUrl = process.argv[4];
230
230
  if (healthUrl === void 0) throw new Error("managed plugin update health URL is required");
@@ -1848,6 +1848,49 @@ Arkme 用户 {v0}|Arkme user {v0}
1848
1848
  return typeof location !== "undefined" && new URLSearchParams(location.search).get("arkmeConversation") === "1";
1849
1849
  }
1850
1850
  //#endregion
1851
+ //#region src/dsh-remote/account-session-observer.ts
1852
+ /** Browser/SDK receive-only invalidation adapter; disposal aborts the subscription. */
1853
+ function observeDshAccountSession(route, fetchImpl, target, changed, options = {}) {
1854
+ const controller = new AbortController();
1855
+ const signal = options.signal ? AbortSignal.any([controller.signal, options.signal]) : controller.signal;
1856
+ (async () => {
1857
+ const response = await fetchImpl(route, {
1858
+ method: "POST",
1859
+ credentials: "same-origin",
1860
+ headers: { "Content-Type": "application/json" },
1861
+ body: JSON.stringify({
1862
+ operation: "remote.session.observe",
1863
+ params: target
1864
+ }),
1865
+ signal
1866
+ });
1867
+ if (!response.ok || !response.headers.get("content-type")?.includes("application/x-ndjson") || !response.body) throw new Error("远程连接不可用");
1868
+ const reader = response.body.getReader(), decoder = new TextDecoder();
1869
+ let buffer = "";
1870
+ try {
1871
+ while (!signal.aborted) {
1872
+ const { value, done } = await reader.read();
1873
+ if (done) throw new Error("远程连接已断开");
1874
+ buffer += decoder.decode(value, { stream: true });
1875
+ if (buffer.length > 4096) throw new Error("远程通知格式无效");
1876
+ let end;
1877
+ while ((end = buffer.indexOf("\n")) >= 0) {
1878
+ const message = JSON.parse(buffer.slice(0, end));
1879
+ buffer = buffer.slice(end + 1);
1880
+ if (message.error) throw new Error(message.error);
1881
+ if (message.changed && !signal.aborted) changed();
1882
+ }
1883
+ }
1884
+ } finally {
1885
+ await reader.cancel().catch(() => void 0);
1886
+ reader.releaseLock();
1887
+ }
1888
+ })().catch((error) => {
1889
+ if (!signal.aborted) options.onError?.(error);
1890
+ });
1891
+ return () => controller.abort();
1892
+ }
1893
+ //#endregion
1851
1894
  //#region src/record-owner-id.ts
1852
1895
  function recordOwnerId(value) {
1853
1896
  if (typeof value === "number") return Number.isSafeInteger(value) && value > 0 ? value : 0;
@@ -3236,6 +3279,25 @@ Arkme 用户 {v0}|Arkme user {v0}
3236
3279
  if (timeout !== void 0) clearTimeout(timeout);
3237
3280
  };
3238
3281
  }
3282
+ async listDshAccountSessions(options = {}, signal) {
3283
+ const result = await this.call("remote.sessions.list", options, signal);
3284
+ if (result.contractVersion !== 1) throw new Error("账号会话协议版本不受支持");
3285
+ return result;
3286
+ }
3287
+ async readDshAccountSession(options, signal) {
3288
+ return await this.call("remote.session.read", options, signal);
3289
+ }
3290
+ async commandDshAccountSession(options, signal) {
3291
+ return await this.call("remote.session.command", options, signal);
3292
+ }
3293
+ /** Event-driven invalidation only. Abort or dispose closes the Host subscription. */
3294
+ observeDshAccountSession(target, changed, options = {}) {
3295
+ return observeDshAccountSession(this.route, this.fetchImpl, target, changed, options);
3296
+ }
3297
+ /** Account-authorized native DSH carrier. Callers retain native RPC result semantics. */
3298
+ async nativeDshRequest(options, signal) {
3299
+ return await this.call("remote.session.native", options, signal);
3300
+ }
3239
3301
  async currentDesktopSession(signal) {
3240
3302
  return await this.call("remote.currentSession", void 0, signal);
3241
3303
  }
@@ -6905,8 +6967,28 @@ Arkme 用户 {v0}|Arkme user {v0}
6905
6967
  }
6906
6968
  //#endregion
6907
6969
  //#region src/client/harness-model-client.tsx
6908
- function ModelSeat({ sessionId, ...props }) {
6909
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeModelSelect, { ...props }, sessionId);
6970
+ function ReadOnlyModelSeat({ projection }) {
6971
+ const value = (0, react.useSyncExternalStore)(projection.subscribe, projection.getSnapshot);
6972
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6973
+ className: "arkme-model-select",
6974
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: arkme_model_select_default }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
6975
+ type: "button",
6976
+ className: "arkme-model-trigger",
6977
+ disabled: true,
6978
+ title: "模型设置请在源电脑修改",
6979
+ children: [
6980
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: value?.next?.model ?? "源实例默认模型" }),
6981
+ value?.next?.reasoningEffort && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("small", { children: [" · ", value.next.reasoningEffort] }),
6982
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6983
+ "aria-hidden": true,
6984
+ children: "⌄"
6985
+ })
6986
+ ]
6987
+ })]
6988
+ });
6989
+ }
6990
+ function ModelSeat(props) {
6991
+ return "projection" in props ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReadOnlyModelSeat, { projection: props.projection }, props.sessionId) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArkmeModelSelect, { ...props }, props.sessionId);
6910
6992
  }
6911
6993
  const inject = [
6912
6994
  "slots",
@@ -6922,10 +7004,10 @@ Arkme 用户 {v0}|Arkme user {v0}
6922
7004
  scope.slots.inject("conversation.input.model", () => scope.slots.register({
6923
7005
  name: "conversation.input.model",
6924
7006
  priority: -100,
6925
- inject: (sessionId) => ({
7007
+ inject: (sessionId) => sessionId.startsWith("arkme:") ? { projection: sessions.binding(sessionId).session.projections.faceOf("modelSelection") } : {
6926
7008
  directory: models.directoryFor(sessionId),
6927
7009
  available: sessions.subagentAddress(sessionId) === void 0
6928
- })
7010
+ }
6929
7011
  }, ModelSeat));
6930
7012
  });
6931
7013
  }
@@ -148,6 +148,49 @@ window.__ModuleLoader__.load({
148
148
  return typeof location !== "undefined" && new URLSearchParams(location.search).get("arkmeConversation") === "1";
149
149
  }
150
150
  //#endregion
151
+ //#region src/dsh-remote/account-session-observer.ts
152
+ /** Browser/SDK receive-only invalidation adapter; disposal aborts the subscription. */
153
+ function observeDshAccountSession(route, fetchImpl, target, changed, options = {}) {
154
+ const controller = new AbortController();
155
+ const signal = options.signal ? AbortSignal.any([controller.signal, options.signal]) : controller.signal;
156
+ (async () => {
157
+ const response = await fetchImpl(route, {
158
+ method: "POST",
159
+ credentials: "same-origin",
160
+ headers: { "Content-Type": "application/json" },
161
+ body: JSON.stringify({
162
+ operation: "remote.session.observe",
163
+ params: target
164
+ }),
165
+ signal
166
+ });
167
+ if (!response.ok || !response.headers.get("content-type")?.includes("application/x-ndjson") || !response.body) throw new Error("远程连接不可用");
168
+ const reader = response.body.getReader(), decoder = new TextDecoder();
169
+ let buffer = "";
170
+ try {
171
+ while (!signal.aborted) {
172
+ const { value, done } = await reader.read();
173
+ if (done) throw new Error("远程连接已断开");
174
+ buffer += decoder.decode(value, { stream: true });
175
+ if (buffer.length > 4096) throw new Error("远程通知格式无效");
176
+ let end;
177
+ while ((end = buffer.indexOf("\n")) >= 0) {
178
+ const message = JSON.parse(buffer.slice(0, end));
179
+ buffer = buffer.slice(end + 1);
180
+ if (message.error) throw new Error(message.error);
181
+ if (message.changed && !signal.aborted) changed();
182
+ }
183
+ }
184
+ } finally {
185
+ await reader.cancel().catch(() => void 0);
186
+ reader.releaseLock();
187
+ }
188
+ })().catch((error) => {
189
+ if (!signal.aborted) options.onError?.(error);
190
+ });
191
+ return () => controller.abort();
192
+ }
193
+ //#endregion
151
194
  //#region src/record-owner-id.ts
152
195
  function recordOwnerId(value) {
153
196
  if (typeof value === "number") return Number.isSafeInteger(value) && value > 0 ? value : 0;
@@ -1536,6 +1579,25 @@ window.__ModuleLoader__.load({
1536
1579
  if (timeout !== void 0) clearTimeout(timeout);
1537
1580
  };
1538
1581
  }
1582
+ async listDshAccountSessions(options = {}, signal) {
1583
+ const result = await this.call("remote.sessions.list", options, signal);
1584
+ if (result.contractVersion !== 1) throw new Error("账号会话协议版本不受支持");
1585
+ return result;
1586
+ }
1587
+ async readDshAccountSession(options, signal) {
1588
+ return await this.call("remote.session.read", options, signal);
1589
+ }
1590
+ async commandDshAccountSession(options, signal) {
1591
+ return await this.call("remote.session.command", options, signal);
1592
+ }
1593
+ /** Event-driven invalidation only. Abort or dispose closes the Host subscription. */
1594
+ observeDshAccountSession(target, changed, options = {}) {
1595
+ return observeDshAccountSession(this.route, this.fetchImpl, target, changed, options);
1596
+ }
1597
+ /** Account-authorized native DSH carrier. Callers retain native RPC result semantics. */
1598
+ async nativeDshRequest(options, signal) {
1599
+ return await this.call("remote.session.native", options, signal);
1600
+ }
1539
1601
  async currentDesktopSession(signal) {
1540
1602
  return await this.call("remote.currentSession", void 0, signal);
1541
1603
  }
@@ -8,6 +8,9 @@ window.__ModuleLoader__.load({
8
8
  /** Same-origin bridge owned and disposed by the embedded session client. */
9
9
  const HARNESS_SESSION_NAVIGATION_KEY = "__arkmeHarnessSessionNavigation";
10
10
  //#endregion
11
+ //#region src/client/harness-session-menu-bridge.ts
12
+ const HARNESS_LOCAL_SESSION_OPEN = "arkme:harness-local-session-open";
13
+ //#endregion
11
14
  //#region src/client/harness-session-selection.ts
12
15
  /** The embedded runtime owns selection. Visibility/presence clears must never erase it. */
13
16
  function observeHarnessSessionSelection(sessions, bridge) {
@@ -30,7 +33,7 @@ window.__ModuleLoader__.load({
30
33
  };
31
34
  const changed = () => {
32
35
  const snapshot = sessions.list.getSnapshot();
33
- if (stopped || snapshot.phase !== "ready" || !snapshot.current || !snapshot.byId[snapshot.current]) return;
36
+ if (stopped || snapshot.phase !== "ready" || !snapshot.current || snapshot.current.startsWith("arkme:") || !snapshot.byId[snapshot.current]) return;
34
37
  const key = JSON.stringify([snapshot.current, snapshot.currentAddress]);
35
38
  if (pending?.key === key) return;
36
39
  if (retry !== void 0) {
@@ -61,8 +64,60 @@ window.__ModuleLoader__.load({
61
64
  "remote.session"
62
65
  ];
63
66
  const REFRESH_MS = 1e4;
67
+ /** Use the public native composer gate; neither draft nor editor DOM is replaced. */
68
+ function lockDisconnectedComposer(sessions, connection, blocksFor) {
69
+ const offline = { reason: "源电脑未连接" };
70
+ let current, blocks, stopBlock;
71
+ const clear = () => {
72
+ stopBlock?.();
73
+ stopBlock = void 0;
74
+ if (current && blocks && blocks.storeFor(current).getSnapshot() === offline) blocks.set(current, void 0);
75
+ };
76
+ const sync = () => {
77
+ const next = sessions.list.getSnapshot().current;
78
+ if (next !== current) {
79
+ clear();
80
+ current = next;
81
+ blocks = current ? blocksFor(current) : void 0;
82
+ if (current && blocks) stopBlock = blocks.storeFor(current).subscribe(sync);
83
+ }
84
+ if (!current || !blocks) return;
85
+ const block = blocks.storeFor(current).getSnapshot();
86
+ if (connection.getSnapshot() !== "connected") {
87
+ if (block === void 0) blocks.set(current, offline);
88
+ } else if (block === offline) blocks.set(current, void 0);
89
+ };
90
+ const stopConnection = connection.subscribe(sync), stopSessions = sessions.list.subscribe(sync);
91
+ sync();
92
+ return () => {
93
+ stopConnection();
94
+ stopSessions();
95
+ clear();
96
+ };
97
+ }
64
98
  /** The iframe reads selection through the public DSH store; Arkme owns visibility. */
65
99
  function apply(ctx) {
100
+ if (window.__ARKME_NATIVE_DIRECTORY__) ctx.inject(["connection"], (scope) => {
101
+ const connection = scope.get("connection");
102
+ const sessions = scope.sessions;
103
+ scope.effect(() => {
104
+ const surface = window.frameElement?.parentElement;
105
+ return lockDisconnectedComposer(sessions, {
106
+ getSnapshot: () => surface?.getAttribute("data-arkme-source-writable") === "true" ? connection.state.getSnapshot() : "disconnected",
107
+ subscribe(listener) {
108
+ const stop = connection.state.subscribe(listener), observer = new MutationObserver(listener);
109
+ if (surface) observer.observe(surface, {
110
+ attributes: true,
111
+ attributeFilter: ["data-arkme-source-writable"]
112
+ });
113
+ return () => {
114
+ stop();
115
+ observer.disconnect();
116
+ };
117
+ }
118
+ }, (id) => (sessions.scope(id)?.get("conversation"))?.blocks);
119
+ }, "arkme: remote composer follows source availability");
120
+ });
66
121
  ctx.effect(() => {
67
122
  const surface = window.frameElement?.parentElement;
68
123
  if (surface?.getAttribute("data-arkme-owned") !== "deepseek-harness-surface") return () => void 0;
@@ -70,7 +125,35 @@ window.__ModuleLoader__.load({
70
125
  const sessions = ctx.sessions;
71
126
  if (sessions === void 0) return () => void 0;
72
127
  const parent = window.parent;
128
+ const query = new URLSearchParams(window.location?.search);
73
129
  const stopPersistence = observeHarnessSessionSelection(sessions, parent?.arkmeDesktop?.sessionSelection);
130
+ let requestedSession = null;
131
+ const restoreRequested = () => {
132
+ if (!requestedSession || !sessions.list.getSnapshot().byId[requestedSession]) return;
133
+ const id = requestedSession;
134
+ requestedSession = null;
135
+ sessions.open(id);
136
+ };
137
+ const selectRequested = (id) => {
138
+ requestedSession = id;
139
+ restoreRequested();
140
+ };
141
+ let observedCurrent = sessions.list.getSnapshot().current;
142
+ const stopRequested = sessions.list.subscribe(() => {
143
+ const current = sessions.list.getSnapshot().current;
144
+ if (current !== observedCurrent) {
145
+ observedCurrent = current;
146
+ requestedSession = null;
147
+ }
148
+ window.__ARKME_NATIVE_DIRECTORY__?.select(current);
149
+ restoreRequested();
150
+ });
151
+ const requested = new MutationObserver(() => selectRequested(surface.getAttribute("data-arkme-open-session")));
152
+ requested.observe(surface, {
153
+ attributes: true,
154
+ attributeFilter: ["data-arkme-open-session", "data-arkme-open-revision"]
155
+ });
156
+ selectRequested(surface.getAttribute("data-arkme-open-session") || query.get("arkme-session"));
74
157
  const frameWindow = window;
75
158
  const navigation = {
76
159
  async has(sessionId) {
@@ -93,11 +176,15 @@ window.__ModuleLoader__.load({
93
176
  if (typeof sessionId !== "string" || sessionId.trim() === "") throw new Error("DSH 对话标识无效");
94
177
  if (typeof sessions.open !== "function") throw new Error("当前 DSH 版本暂不支持打开任务");
95
178
  sessions.open(sessionId);
179
+ document.dispatchEvent(new Event(HARNESS_LOCAL_SESSION_OPEN));
96
180
  }
97
181
  };
98
182
  frameWindow[HARNESS_SESSION_NAVIGATION_KEY] = navigation;
99
183
  const disposeNavigation = () => {
184
+ requestedSession = null;
100
185
  stopPersistence();
186
+ stopRequested();
187
+ requested.disconnect();
101
188
  if (frameWindow["__arkmeHarnessSessionNavigation"] === navigation) delete frameWindow[HARNESS_SESSION_NAVIGATION_KEY];
102
189
  };
103
190
  if (apiPath === void 0 || !/^\/[A-Za-z0-9/_-]+$/.test(apiPath)) return disposeNavigation;
@@ -109,6 +196,7 @@ window.__ModuleLoader__.load({
109
196
  let timer;
110
197
  let fingerprint = "";
111
198
  let renew = false;
199
+ let focused = false;
112
200
  let controller;
113
201
  const report = async () => {
114
202
  if (stopped) return;
@@ -122,9 +210,11 @@ window.__ModuleLoader__.load({
122
210
  dirty = false;
123
211
  const accountId = surface.getAttribute("data-arkme-account-id") ?? "";
124
212
  const current = sessions.list.getSnapshot().current;
125
- const sessionRef = surface.getAttribute("data-arkme-follow-session") === "true" ? current ?? null : null;
213
+ const sessionRef = surface.getAttribute("data-arkme-follow-session") === "true" && !surface.getAttribute("data-arkme-remote-session") ? current && !current.startsWith("arkme:") ? current : null : null;
126
214
  renew = accountId !== "" && sessionRef !== null;
127
215
  fingerprint = JSON.stringify([accountId, sessionRef]);
216
+ const reportFocus = focused;
217
+ focused = false;
128
218
  if (accountId !== "") {
129
219
  controller = new AbortController();
130
220
  const deadline = setTimeout(() => {
@@ -140,7 +230,8 @@ window.__ModuleLoader__.load({
140
230
  accountId,
141
231
  windowRef,
142
232
  revision: ++revision,
143
- sessionRef
233
+ sessionRef,
234
+ focused: reportFocus
144
235
  }
145
236
  }),
146
237
  signal: controller.signal
@@ -157,8 +248,13 @@ window.__ModuleLoader__.load({
157
248
  };
158
249
  const changed = () => {
159
250
  const accountId = surface.getAttribute("data-arkme-account-id") ?? "";
160
- const current = surface.getAttribute("data-arkme-follow-session") === "true" ? sessions.list.getSnapshot().current ?? null : null;
161
- if (JSON.stringify([accountId, current]) !== fingerprint) report();
251
+ const current = surface.getAttribute("data-arkme-follow-session") === "true" && !surface.getAttribute("data-arkme-remote-session") ? sessions.list.getSnapshot().current ?? null : null;
252
+ const localCurrent = current?.startsWith("arkme:") ? null : current;
253
+ if (JSON.stringify([accountId, localCurrent]) !== fingerprint) report();
254
+ };
255
+ const onFocus = () => {
256
+ focused = true;
257
+ report();
162
258
  };
163
259
  const clearSelection = () => {
164
260
  controller?.abort();
@@ -183,10 +279,15 @@ window.__ModuleLoader__.load({
183
279
  const observer = new MutationObserver(changed);
184
280
  observer.observe(surface, {
185
281
  attributes: true,
186
- attributeFilter: ["data-arkme-follow-session", "data-arkme-account-id"]
282
+ attributeFilter: [
283
+ "data-arkme-follow-session",
284
+ "data-arkme-account-id",
285
+ "data-arkme-remote-session"
286
+ ]
187
287
  });
188
288
  const unsubscribe = sessions.list.subscribe(changed);
189
289
  document.addEventListener("visibilitychange", changed);
290
+ window.addEventListener("focus", onFocus);
190
291
  window.addEventListener("pagehide", clearSelection);
191
292
  window.addEventListener("pageshow", changed);
192
293
  report();
@@ -197,6 +298,7 @@ window.__ModuleLoader__.load({
197
298
  observer.disconnect();
198
299
  unsubscribe();
199
300
  document.removeEventListener("visibilitychange", changed);
301
+ window.removeEventListener("focus", onFocus);
200
302
  window.removeEventListener("pagehide", clearSelection);
201
303
  window.removeEventListener("pageshow", changed);
202
304
  };
@@ -205,6 +307,7 @@ window.__ModuleLoader__.load({
205
307
  //#endregion
206
308
  exports.apply = apply;
207
309
  exports.inject = inject;
310
+ exports.lockDisconnectedComposer = lockDisconnectedComposer;
208
311
  return module.exports;
209
312
  }
210
313
  });