@senguoyun/dsh-arkme 0.1.55 → 0.1.57

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.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as ARKME_DEFAULT_SHARE_WEBSITE, A as inspectNativeBundleArtifactV3, At as createDesktopLifecycleReader, D as bundleSha256, Dt as ArkmePluginError, E as arkmeSandboxEntryId, Et as normalizeRecentEmojiIds, F as assertExtensionArtifactSize, Ft as __toCommonJS, G as validateVoiceprintPcm16Wav, I as canonicalExtensionJson, J as arkmeRequiredLinkMetadataFallback, K as arkmeExtensionShareRefFromLink, L as sha256Hex, M as packLocalNativeBundleDirectoryV3, Mt as __esmMin, N as readNativeBundleTarballV3, Nt as __exportAll, O as canonicalBundleJson, Ot as retryAfterMillis, P as renderArkmeSandboxHostEntry, Pt as __require, Q as parseArkmeRecordReeditAttachments, R as unpackArkmeExtension, S as ARKME_BUNDLE_ARTIFACT_KIND, St as sameRecordingImportIdentity, T as ArkmeBundleArtifactError, Tt as isRecentEmojiId, U as ARKME_EXTENSION_RUNTIME_UNAVAILABLE_MESSAGE, W as ArkmeService, X as arkmeRichBackgroundSound, Y as arkmeFileBackgroundSound, Z as ArkmeRecordReeditDraftConflict, _ as arkmeClientContentDigest, _t as SecretValue, at as ARKME_WORLD_PUBLISH_MAX_IMAGE_BYTES, b as verifyExtensionResolutionSignature, bt as isUnresolvedRecordingImportJob, c as persistentExtensionBundleDirectory, ct as mergeMemberJoinEvents, d as readPersistentExtensionActivation, dt as ARKME_TOOL_FILE_MAX_BYTES, et as ARKME_PROVIDER_CONTRACT_VERSION, f as refreshPersistentClientWrapper, ft as arkmeCanInlineLocalFile, g as activeProfileExtensionOwnerConflicts, gt as ArkmeOutgoingCallError, h as renderArkmeBundleClientBundle, ht as isArkmeBotAvatarRef, i as invokePersistentArkmeExtension, it as ARKME_WORLD_PUBLISH_MAX_IMAGES, j as packBundleFiles, jt as __commonJSMin, k as inspectBundleArtifact, kt as recordOwnerId, l as persistentExtensionPackageIdentity, lt as validateMemberUpdate, m as writePersistentExtensionActivation, mt as arkmePickedFileKind, o as persistentArkmeExtensionRuntimeState, ot as applyMemberUpdate, p as repairPersistentExtensionInstallation, pt as arkmeNormalizedFileMimeType, q as arkmeIsGenericLinkMetadataTitle, r as deactivatePersistentArkmeExtension, s as materializePersistentExtensionBundle, st as cachedMemberItem, t as activatePersistentArkmeExtension, u as quarantinePersistentExtension, ut as ARKME_RUNTIME_INSTANCE_ID, v as arkmeClientContentDigestFromSource, vt as ArkmeDirectMessageAdmissionError, w as ARKME_NATIVE_BUNDLE_ARTIFACT_KIND, wt as recordingImportFileNameKey, x as verifyNativeBundleResolutionSignature, xt as recordingImportFileKind, y as verifyBundleResolutionSignature, yt as isRecordingInstantOnOrAfterUnixEpoch, z as ARKME_EXTENSION_FORMAT } from "./persistent-runtime-Bsk6in2a.js";
1
+ import { $ as ARKME_DEFAULT_SHARE_WEBSITE, A as inspectNativeBundleArtifactV3, At as createDesktopLifecycleReader, D as bundleSha256, Dt as ArkmePluginError, E as arkmeSandboxEntryId, Et as normalizeRecentEmojiIds, F as assertExtensionArtifactSize, Ft as __toCommonJS, G as validateVoiceprintPcm16Wav, I as canonicalExtensionJson, J as arkmeRequiredLinkMetadataFallback, K as arkmeExtensionShareRefFromLink, L as sha256Hex, M as packLocalNativeBundleDirectoryV3, Mt as __esmMin, N as readNativeBundleTarballV3, Nt as __exportAll, O as canonicalBundleJson, Ot as retryAfterMillis, P as renderArkmeSandboxHostEntry, Pt as __require, Q as parseArkmeRecordReeditAttachments, R as unpackArkmeExtension, S as ARKME_BUNDLE_ARTIFACT_KIND, St as sameRecordingImportIdentity, T as ArkmeBundleArtifactError, Tt as isRecentEmojiId, U as ARKME_EXTENSION_RUNTIME_UNAVAILABLE_MESSAGE, W as ArkmeService, X as arkmeRichBackgroundSound, Y as arkmeFileBackgroundSound, Z as ArkmeRecordReeditDraftConflict, _ as arkmeClientContentDigest, _t as SecretValue, at as ARKME_WORLD_PUBLISH_MAX_IMAGE_BYTES, b as verifyExtensionResolutionSignature, bt as isUnresolvedRecordingImportJob, c as persistentExtensionBundleDirectory, ct as mergeMemberJoinEvents, d as readPersistentExtensionActivation, dt as ARKME_TOOL_FILE_MAX_BYTES, et as ARKME_PROVIDER_CONTRACT_VERSION, f as refreshPersistentClientWrapper, ft as arkmeCanInlineLocalFile, g as activeProfileExtensionOwnerConflicts, gt as ArkmeOutgoingCallError, h as renderArkmeBundleClientBundle, ht as isArkmeBotAvatarRef, i as invokePersistentArkmeExtension, it as ARKME_WORLD_PUBLISH_MAX_IMAGES, j as packBundleFiles, jt as __commonJSMin, k as inspectBundleArtifact, kt as recordOwnerId, l as persistentExtensionPackageIdentity, lt as validateMemberUpdate, m as writePersistentExtensionActivation, mt as arkmePickedFileKind, o as persistentArkmeExtensionRuntimeState, ot as applyMemberUpdate, p as repairPersistentExtensionInstallation, pt as arkmeNormalizedFileMimeType, q as arkmeIsGenericLinkMetadataTitle, r as deactivatePersistentArkmeExtension, s as materializePersistentExtensionBundle, st as cachedMemberItem, t as activatePersistentArkmeExtension, u as quarantinePersistentExtension, ut as ARKME_RUNTIME_INSTANCE_ID, v as arkmeClientContentDigestFromSource, vt as ArkmeDirectMessageAdmissionError, w as ARKME_NATIVE_BUNDLE_ARTIFACT_KIND, wt as recordingImportFileNameKey, x as verifyNativeBundleResolutionSignature, xt as recordingImportFileKind, y as verifyBundleResolutionSignature, yt as isRecordingInstantOnOrAfterUnixEpoch, z as ARKME_EXTENSION_FORMAT } from "./persistent-runtime-BnDj8qcY.js";
2
2
  import { _ as parsePluginUpdateManifest, b as validatePluginUpdateServiceOrigin, d as writePluginUpdateLifecycleLog, f as PluginUpdateInstallStateStore, g as existingCachedPluginArtifactPath, h as downloadAndCachePluginArtifact, m as PluginUpdateArtifactError, n as buildTargetInstallArgs, o as reconcilePluginUpdaterProfilePolicy, p as ARKME_PLUGIN_PACKAGE_NAME$1, t as assertTargetArtifactIntegrity, u as detachManagedProfilePluginLink, v as pluginUpdateEndpointUrl, y as validatePluginUpdateArtifactOrigin } from "./plugin-updater-helper-y7wzJLOx.js";
3
3
  import { a as securePrivateDirectory, c as securePrivateFileSync, i as prepareProfilePackageManager, n as isArkmeProfilePackageName, o as securePrivateDirectorySync, r as localExtensionPnpmArgs, s as securePrivateFile, t as applyArkmeProfileBundlePolicy } from "./profile-bundle-policy-DLXDyohJ.js";
4
4
  import { i as invokeArkmeBundle, n as arkmeBundleActive, r as deactivateArkmeBundle } from "./bundle-runtime-CE73h3vS.js";
@@ -11268,7 +11268,7 @@ function createArkmeHostApi(service, options) {
11268
11268
  ].includes(request.operation) && origin === void 0) throw new ArkmePluginError("origin-required", "该敏感变更必须从当前 DSH 页面发起", false, 403);
11269
11269
  writeJson$5(res, 200, {
11270
11270
  ok: true,
11271
- value: await dispatchArkmeHostOperation(service, request.operation, params, options.updateManager, options.extensionManager?.(), options.extensionInstallTasks?.(), options.ownedExtensionInventory?.(), controller.signal, options.remoteHost?.(), options.desktopQuarantine, options.openApiMcpController, options.teamService)
11271
+ value: await dispatchArkmeHostOperation(service, request.operation, params, options.updateManager, options.extensionManager?.(), options.extensionInstallTasks?.(), options.ownedExtensionInventory?.(), controller.signal, options.remoteHost?.(), options.desktopQuarantine, options.openApiMcpController, options.teamService, options.remoteUnavailableReason)
11272
11272
  });
11273
11273
  } catch (error) {
11274
11274
  if (controller.signal.aborted && res.destroyed) return;
@@ -11291,7 +11291,7 @@ function createArkmeHostApi(service, options) {
11291
11291
  }
11292
11292
  };
11293
11293
  }
11294
- async function dispatchArkmeHostOperation(service, operation, params, updateManager, extensionManager, extensionInstallTasks, ownedExtensionInventory, requestSignal, remoteHost, desktopQuarantine, openApiMcpController, teamService) {
11294
+ async function dispatchArkmeHostOperation(service, operation, params, updateManager, extensionManager, extensionInstallTasks, ownedExtensionInventory, requestSignal, remoteHost, desktopQuarantine, openApiMcpController, teamService, remoteUnavailableReason) {
11295
11295
  switch (operation) {
11296
11296
  case "provider.capabilities": {
11297
11297
  const capabilities = service.providerCapabilities();
@@ -11378,17 +11378,17 @@ async function dispatchArkmeHostOperation(service, operation, params, updateMana
11378
11378
  itemId: stringParam(item, "itemId"),
11379
11379
  jotmoId: stringParam(item, "jotmoId")
11380
11380
  })), requestSignal);
11381
- case "remote.currentSession": return await requireRemoteHost(remoteHost).currentSession();
11381
+ case "remote.currentSession": return await requireRemoteHost(remoteHost, remoteUnavailableReason).currentSession();
11382
11382
  case "remote.reportCurrentSession":
11383
- requireRemoteHost(remoteHost).reportCurrentSession({
11383
+ requireRemoteHost(remoteHost, remoteUnavailableReason).reportCurrentSession({
11384
11384
  accountId: stringParam(params, "accountId"),
11385
11385
  windowRef: stringParam(params, "windowRef"),
11386
11386
  revision: numberParam(params, "revision", NaN),
11387
11387
  sessionRef: params.sessionRef === null ? null : stringParam(params, "sessionRef")
11388
11388
  });
11389
11389
  return { accepted: true };
11390
- case "remote.getStatus": return requireRemoteHost(remoteHost).getStatus();
11391
- case "remote.renameDesktop": return await requireRemoteHost(remoteHost).renameDesktop(stringParam(params, "displayName"));
11390
+ case "remote.getStatus": return requireRemoteHost(remoteHost, remoteUnavailableReason).getStatus();
11391
+ case "remote.renameDesktop": return await requireRemoteHost(remoteHost, remoteUnavailableReason).renameDesktop(stringParam(params, "displayName"));
11392
11392
  case "billing.quota": return await service.billingQuota();
11393
11393
  case "billing.products": return await service.billingProducts();
11394
11394
  case "billing.order.create": return await service.createBillingOrder({
@@ -12235,8 +12235,8 @@ function requireUpdateManager(updateManager) {
12235
12235
  if (updateManager === void 0) throw new ArkmePluginError("plugin-update-unavailable", "插件更新检查暂不可用", true, 503);
12236
12236
  return updateManager;
12237
12237
  }
12238
- function requireRemoteHost(host) {
12239
- if (host === void 0) throw new ArkmePluginError("CAPABILITY_UNSUPPORTED", "当前 DSH 未加载远控 Host", false, 503);
12238
+ function requireRemoteHost(host, reason) {
12239
+ if (host === void 0) throw new ArkmePluginError("CAPABILITY_UNSUPPORTED", reason?.() ?? "当前 DSH 未加载远控 Host", false, 503);
12240
12240
  return host;
12241
12241
  }
12242
12242
  function requireExtensionInstallTasks(tasks) {
@@ -14980,7 +14980,7 @@ var TeamService = class {
14980
14980
  ...pageCursor === void 0 ? {} : { page_cursor: pageCursor }
14981
14981
  };
14982
14982
  const source = object$1(await this.reads.runOwnerRead("openapi:teams:list", parameters, (signal) => this.execute(signal, (active) => this.client.list(parameters, active)), options.signal), "团队列表响应无效");
14983
- const items = array(source.items, "团队列表响应无效").map(team);
14983
+ const items = array$1(source.items, "团队列表响应无效").map(team);
14984
14984
  const totalCount = nonNegativeInteger(source.total_count, "团队列表响应无效");
14985
14985
  const hasMore = boolean(source.has_more, "团队列表响应无效");
14986
14986
  const nextPageCursor = responseCursor(source.next_page_cursor, hasMore);
@@ -15009,13 +15009,13 @@ var TeamService = class {
15009
15009
  ...pageCursor === void 0 ? {} : { page_cursor: pageCursor }
15010
15010
  };
15011
15011
  });
15012
- const responseItems = array(object$1(await this.execute(signal, (active) => this.client.resolve({ items: requestItems }, active)), "团队解析响应无效").items, "团队解析响应无效");
15012
+ const responseItems = array$1(object$1(await this.execute(signal, (active) => this.client.resolve({ items: requestItems }, active)), "团队解析响应无效").items, "团队解析响应无效");
15013
15013
  if (responseItems.length !== requestItems.length) throw invalidResponse();
15014
15014
  return responseItems.map((value, index) => {
15015
15015
  const source = object$1(value, "团队解析响应无效");
15016
15016
  const itemId = requiredString$2(source.item_id, 64, "团队解析响应无效");
15017
15017
  if (itemId !== requestItems[index].item_id) throw invalidResponse();
15018
- const candidates = array(source.candidates, "团队解析响应无效").map(team);
15018
+ const candidates = array$1(source.candidates, "团队解析响应无效").map(team);
15019
15019
  if (candidates.length > requestItems[index].limit) throw invalidResponse();
15020
15020
  const hasMore = boolean(source.has_more, "团队解析响应无效");
15021
15021
  const nextPageCursor = responseCursor(source.next_page_cursor, hasMore);
@@ -15039,7 +15039,7 @@ var TeamService = class {
15039
15039
  }, signal)), "团队成员响应无效");
15040
15040
  const teamValue = team(source.team);
15041
15041
  if (teamValue.teamRef !== normalizedTeamRef) throw invalidResponse();
15042
- const items = array(source.items, "团队成员响应无效").map(member);
15042
+ const items = array$1(source.items, "团队成员响应无效").map(member);
15043
15043
  const totalCount = nonNegativeInteger(source.total_count, "团队成员响应无效");
15044
15044
  const hasMore = boolean(source.has_more, "团队成员响应无效");
15045
15045
  const nextPageCursor = responseCursor(source.next_page_cursor, hasMore);
@@ -15178,7 +15178,7 @@ function member(value) {
15178
15178
  };
15179
15179
  }
15180
15180
  function writeResultSources(data, itemIds) {
15181
- const values = array(object$1(data, "团队治理响应无效").items, "团队治理响应无效");
15181
+ const values = array$1(object$1(data, "团队治理响应无效").items, "团队治理响应无效");
15182
15182
  if (values.length !== itemIds.length) throw invalidResponse();
15183
15183
  return values.map((value, index) => {
15184
15184
  const source = object$1(value, "团队治理响应无效");
@@ -15270,7 +15270,7 @@ function object$1(value, message) {
15270
15270
  if (value === null || typeof value !== "object" || Array.isArray(value)) throw new ArkmePluginError("team-openapi-invalid-response", message, true, 503);
15271
15271
  return value;
15272
15272
  }
15273
- function array(value, message) {
15273
+ function array$1(value, message) {
15274
15274
  if (!Array.isArray(value)) throw new ArkmePluginError("team-openapi-invalid-response", message, true, 503);
15275
15275
  return value;
15276
15276
  }
@@ -20512,14 +20512,14 @@ var ArkmeExtensionManager = class {
20512
20512
  };
20513
20513
  //#endregion
20514
20514
  //#region src/extensions/publish-client.ts
20515
- function record$4(value) {
20515
+ function record$5(value) {
20516
20516
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
20517
20517
  }
20518
20518
  function legacyManifest(value) {
20519
- const manifest = record$4(value);
20520
- const runtime = record$4(manifest?.runtime);
20521
- const halves = record$4(manifest?.halves);
20522
- const entrypoints = record$4(manifest?.entrypoints);
20519
+ const manifest = record$5(value);
20520
+ const runtime = record$5(manifest?.runtime);
20521
+ const halves = record$5(manifest?.halves);
20522
+ const entrypoints = record$5(manifest?.entrypoints);
20523
20523
  const permissions = manifest?.permissions;
20524
20524
  if (manifest?.format !== "arkme-cordis-extension" || manifest.format_version !== 1 || typeof manifest.name !== "string" || typeof manifest.description !== "string" || typeof manifest.version !== "string" || typeof runtime?.dsh !== "string" || typeof runtime.arkme_provider_contract !== "number" || typeof halves?.host !== "boolean" || typeof halves.client !== "boolean" || !Array.isArray(permissions) || !permissions.every((permission) => typeof permission === "string") || entrypoints === void 0 || entrypoints.host !== void 0 && entrypoints.host !== "host.js" || entrypoints.client !== void 0 && entrypoints.client !== "client.js") return void 0;
20525
20525
  return {
@@ -29809,13 +29809,8 @@ function registerArkmeTools(ctx, ports, profile = "business", presentation) {
29809
29809
  }
29810
29810
  [...fileToolModules];
29811
29811
  //#endregion
29812
- //#region src/dsh-remote/types.ts
29813
- const DSH_REMOTE_PROTOCOL = "dsh.remote";
29814
- const DSH_REMOTE_MAX_FRAME_BYTES = 60 * 1024;
29815
- const DSH_REMOTE_MAX_PAGE_RESULT_BYTES = 40 * 1024;
29816
- //#endregion
29817
29812
  //#region src/dsh-remote/dsh-event-contract.ts
29818
- function record$3(value) {
29813
+ function record$4(value) {
29819
29814
  if (value === null || typeof value !== "object" || Array.isArray(value)) throw new DshRemoteError("REMOTE_TRANSPORT_FAILED", "DSH HistoryEntry 结构无效", true);
29820
29815
  return value;
29821
29816
  }
@@ -29833,7 +29828,7 @@ function finiteNumber(value, field) {
29833
29828
  return value;
29834
29829
  }
29835
29830
  function snapshotDshHistoryEntry(value) {
29836
- const source = record$3(value.event);
29831
+ const source = record$4(value.event);
29837
29832
  if (typeof source.type !== "string" || source.type.length === 0 || !Number.isSafeInteger(source.seq) || Number(source.seq) < 0) throw new DshRemoteError("REMOTE_TRANSPORT_FAILED", "DSH SessionEvent 信封无效", true);
29838
29833
  const event = {
29839
29834
  type: source.type,
@@ -29851,7 +29846,7 @@ function snapshotDshHistoryEntry(value) {
29851
29846
  event.ignorable = true;
29852
29847
  }
29853
29848
  if (value.view === void 0) return { event };
29854
- const viewSource = record$3(value.view);
29849
+ const viewSource = record$4(value.view);
29855
29850
  if (viewSource.for !== "call" && viewSource.for !== "result" || viewSource.view === null || typeof viewSource.view !== "object" || Array.isArray(viewSource.view)) throw new DshRemoteError("REMOTE_TRANSPORT_FAILED", "DSH ToolEventView 无效", true);
29856
29851
  return {
29857
29852
  event,
@@ -29874,6 +29869,331 @@ function dshTranscriptHistoryEntries(entries) {
29874
29869
  for (const { event } of entries) if (event.type === "assistant/message" && event.surfaceOp === "append") for (const seq of event.sourceEventSeqs ?? []) covered.add(seq);
29875
29870
  return entries.filter(({ event }) => event.type !== "assistant/chunk" || !covered.has(event.seq));
29876
29871
  }
29872
+ //#endregion
29873
+ //#region src/dsh-remote/gateway-api.ts
29874
+ function record$3(value) {
29875
+ if (value === null || typeof value !== "object" || Array.isArray(value)) throw new DshRemoteError("REMOTE_INVALID_RESPONSE", "DSH Gateway 返回了无效对象");
29876
+ return value;
29877
+ }
29878
+ function text(value) {
29879
+ if (typeof value !== "string" || value.length === 0) throw new DshRemoteError("REMOTE_INVALID_RESPONSE", "DSH Gateway 缺少标识");
29880
+ return value;
29881
+ }
29882
+ function array(value) {
29883
+ if (!Array.isArray(value)) throw new DshRemoteError("REMOTE_INVALID_RESPONSE", "DSH Gateway 返回了无效列表");
29884
+ return value;
29885
+ }
29886
+ /** Keep the existing remote protocol/projections; translate only the DSH API boundary. */
29887
+ function createDshGatewayApi(ctx, gateway, connection, lifetime) {
29888
+ const pending = /* @__PURE__ */ new Map();
29889
+ const invoke = async (method, request, signal = lifetime) => {
29890
+ signal.throwIfAborted();
29891
+ return await gateway.invoke({
29892
+ namespace: "session",
29893
+ method,
29894
+ args: request === void 0 ? {} : { [method === "list" ? "_request" : "request"]: request },
29895
+ signal
29896
+ });
29897
+ };
29898
+ const wrap = (operation) => async (request) => {
29899
+ try {
29900
+ return {
29901
+ rpcId: request.rpcId,
29902
+ result: {
29903
+ ok: true,
29904
+ value: await operation(request.payload, request.rpcId)
29905
+ }
29906
+ };
29907
+ } catch (error) {
29908
+ if (error instanceof DshRemoteError) throw error;
29909
+ if (error === null || typeof error !== "object") throw error;
29910
+ const failure = record$3(error);
29911
+ if (typeof failure.code !== "string") throw error;
29912
+ return {
29913
+ rpcId: request.rpcId,
29914
+ result: {
29915
+ ok: false,
29916
+ error: {
29917
+ code: {
29918
+ "session/not-found": "session-not-found",
29919
+ "workspace/not-found": "workspace-not-found",
29920
+ "workspace/invalid-path": "workspace-invalid-path",
29921
+ "session/agent-busy": "agent-busy",
29922
+ "session/steer-unavailable": "steer-unavailable",
29923
+ "session/queue-item-not-found": "queue-item-not-found"
29924
+ }[failure.code] ?? failure.code,
29925
+ message: String(failure.message ?? "DSH 请求失败")
29926
+ }
29927
+ }
29928
+ };
29929
+ }
29930
+ };
29931
+ async function opening(namespace, method, args) {
29932
+ const controller = new AbortController();
29933
+ const signal = AbortSignal.any([
29934
+ lifetime,
29935
+ controller.signal,
29936
+ AbortSignal.timeout(3e4)
29937
+ ]);
29938
+ signal.throwIfAborted();
29939
+ const iterator = (await gateway.stream({
29940
+ namespace,
29941
+ method,
29942
+ args,
29943
+ signal
29944
+ }))[Symbol.asyncIterator]();
29945
+ try {
29946
+ const first = await iterator.next();
29947
+ if (first.done) throw new DshRemoteError("REMOTE_INVALID_RESPONSE", `DSH ${namespace}.${method} 缺少初始快照`);
29948
+ return record$3(first.value);
29949
+ } finally {
29950
+ controller.abort();
29951
+ await iterator.return?.();
29952
+ }
29953
+ }
29954
+ const api = {
29955
+ workspace: { list: wrap(async () => {
29956
+ const frame = await opening("workspace", "follow", {});
29957
+ if (frame.type !== "baseline") throw new DshRemoteError("REMOTE_INVALID_RESPONSE", "DSH Workspace 缺少 baseline");
29958
+ const value = record$3(frame.value);
29959
+ return {
29960
+ items: array(value.items),
29961
+ archivedSessionIds: array(value.archivedSessionIds)
29962
+ };
29963
+ }) },
29964
+ sessions: {
29965
+ list: wrap(async (payload) => record$3(await invoke("list", payload))),
29966
+ create: wrap(async (payload) => record$3(await invoke("create", payload))),
29967
+ modelCatalog: wrap(async () => record$3(await invoke("modelCatalog", void 0))),
29968
+ selectModel: wrap(async (payload) => record$3(await invoke("selectModel", payload))),
29969
+ prompt: wrap(async (payload, requestId) => record$3(await invoke("prompt", {
29970
+ ...payload,
29971
+ requestId
29972
+ }))),
29973
+ cancel: wrap(async (payload) => record$3(await invoke("cancel", payload))),
29974
+ history: wrap(async (payload) => {
29975
+ const address = {
29976
+ kind: "session",
29977
+ sessionId: payload.sessionId
29978
+ };
29979
+ const snapshot = await opening("session", "follow", { request: {
29980
+ address,
29981
+ maxMessages: payload.maxMessages
29982
+ } });
29983
+ if (snapshot.type !== "snapshot" || !Number.isSafeInteger(snapshot.cursor)) throw new DshRemoteError("REMOTE_INVALID_RESPONSE", "DSH Session 缺少日志快照");
29984
+ const page = payload.beforeSeq === void 0 ? snapshot : record$3(await invoke("page", {
29985
+ address,
29986
+ throughSeq: snapshot.cursor,
29987
+ beforeSeq: payload.beforeSeq,
29988
+ maxMessages: payload.maxMessages
29989
+ }));
29990
+ return {
29991
+ events: array(page.records).map((item) => snapshotDshHistoryEntry({ event: record$3(item).event })),
29992
+ hasMore: page.hasMore === true,
29993
+ projections: record$3(snapshot.projections)
29994
+ };
29995
+ })
29996
+ },
29997
+ events: { mux: (_request, signal) => events(signal) },
29998
+ respond: async (message) => {
29999
+ const item = pending.get(message.rpcId);
30000
+ if (item === void 0 || item.signal.aborted) return {
30001
+ accepted: false,
30002
+ reason: "interaction-resolved"
30003
+ };
30004
+ const value = record$3(message.result.value);
30005
+ if (value.sessionId !== item.sessionId) return {
30006
+ accepted: false,
30007
+ reason: "session-mismatch"
30008
+ };
30009
+ const outcome = item.kind === "question" ? value.answer : value.outcome;
30010
+ const result = await sendResult(item.clientId, message.rpcId, {
30011
+ kind: "result",
30012
+ value: outcome
30013
+ }, item.signal);
30014
+ pending.delete(message.rpcId);
30015
+ return result;
30016
+ }
30017
+ };
30018
+ async function sendResult(clientId, eventId, outcome, signal) {
30019
+ const response = await connection.createSharedFetchHandler("/api").fetch(new Request("http://localhost/api/$events/result", {
30020
+ method: "POST",
30021
+ headers: { "content-type": "application/json" },
30022
+ signal,
30023
+ body: JSON.stringify({
30024
+ type: "client-request",
30025
+ rpcId: randomUUID(),
30026
+ method: "$events/result",
30027
+ payload: { args: {
30028
+ clientId,
30029
+ eventId,
30030
+ outcome
30031
+ } }
30032
+ })
30033
+ }));
30034
+ const result = record$3(record$3(await response.json()).result);
30035
+ if (!response.ok || result.ok !== true) throw new DshRemoteError("REMOTE_TRANSPORT_FAILED", "DSH 交互应答失败", true);
30036
+ return { accepted: true };
30037
+ }
30038
+ async function* events(parentSignal) {
30039
+ const controller = new AbortController();
30040
+ const signal = AbortSignal.any([
30041
+ lifetime,
30042
+ parentSignal,
30043
+ controller.signal
30044
+ ]);
30045
+ const frames = [];
30046
+ let bytes = 0;
30047
+ let failure;
30048
+ let wake;
30049
+ const notify = () => {
30050
+ wake?.();
30051
+ wake = void 0;
30052
+ };
30053
+ const fail = (error) => {
30054
+ failure ??= error;
30055
+ controller.abort();
30056
+ notify();
30057
+ };
30058
+ const push = (payload, rpcId = randomUUID()) => {
30059
+ if (signal.aborted) return;
30060
+ try {
30061
+ const frame = {
30062
+ rpcId,
30063
+ payload
30064
+ };
30065
+ const size = Buffer.byteLength(JSON.stringify(frame));
30066
+ if (frames.length >= 1024 || bytes + size > 8 * 1024 * 1024) throw new DshRemoteError("REMOTE_TRANSPORT_FAILED", "DSH 事件积压超限,重新建立快照", true);
30067
+ frames.push({
30068
+ frame,
30069
+ bytes: size
30070
+ });
30071
+ bytes += size;
30072
+ notify();
30073
+ } catch (error) {
30074
+ fail(error);
30075
+ }
30076
+ };
30077
+ const off = ctx.on("session/event", ((session, event) => {
30078
+ try {
30079
+ push({
30080
+ type: "session/event",
30081
+ sessionId: session.id,
30082
+ event: snapshotDshHistoryEntry({ event }).event
30083
+ });
30084
+ } catch (error) {
30085
+ fail(error);
30086
+ }
30087
+ }), { global: true });
30088
+ signal.addEventListener("abort", notify, { once: true });
30089
+ async function consume(stream, accept) {
30090
+ try {
30091
+ for await (const frame of await stream) {
30092
+ if (signal.aborted) break;
30093
+ await accept(record$3(frame));
30094
+ }
30095
+ if (!signal.aborted) fail(/* @__PURE__ */ new Error("DSH event stream ended"));
30096
+ } catch (error) {
30097
+ if (!signal.aborted) fail(error);
30098
+ }
30099
+ }
30100
+ let clientId;
30101
+ const tasks = [consume(gateway.wireStream.open("$events", { args: {} }, signal), async (frame) => {
30102
+ if (frame.type === "ready") {
30103
+ clientId = text(frame.clientId);
30104
+ return;
30105
+ }
30106
+ if (frame.type === "cancel") {
30107
+ const item = pending.get(text(frame.eventId));
30108
+ pending.delete(text(frame.eventId));
30109
+ if (item !== void 0) push(item.kind === "question" ? {
30110
+ type: "question/resolved",
30111
+ questionRpcId: frame.eventId
30112
+ } : {
30113
+ type: "approval/resolved",
30114
+ sessionId: item.sessionId,
30115
+ approvalId: frame.eventId
30116
+ });
30117
+ return;
30118
+ }
30119
+ if (frame.type !== "waterfall" || clientId === void 0) return;
30120
+ if (!["user-questions/request", "approval/request"].includes(text(frame.event))) {
30121
+ await sendResult(clientId, text(frame.eventId), { kind: "next" }, signal);
30122
+ return;
30123
+ }
30124
+ if (pending.size >= 256) throw new Error("DSH pending interaction limit exceeded");
30125
+ const kind = frame.event === "user-questions/request" ? "question" : "approval";
30126
+ const request = record$3(frame.request);
30127
+ pending.set(text(frame.eventId), {
30128
+ clientId,
30129
+ sessionId: text(frame.agentId),
30130
+ kind,
30131
+ signal
30132
+ });
30133
+ push(kind === "question" ? {
30134
+ type: "question/requested",
30135
+ sessionId: frame.agentId,
30136
+ questions: request.questions
30137
+ } : {
30138
+ type: "approval/requested",
30139
+ sessionId: frame.agentId,
30140
+ approvalId: frame.eventId,
30141
+ toolName: request.toolName,
30142
+ reason: request.reason
30143
+ }, text(frame.eventId));
30144
+ }), consume(gateway.stream({
30145
+ namespace: "session",
30146
+ method: "control",
30147
+ args: {},
30148
+ signal
30149
+ }), (frame) => {
30150
+ if (frame.type === "projection" && frame.key === "goal") push({
30151
+ ...frame,
30152
+ type: "session/projection"
30153
+ });
30154
+ if (frame.type === "baseline") for (const [sessionId, value] of Object.entries(record$3(record$3(frame.value).projections))) {
30155
+ const projection = record$3(value);
30156
+ push({
30157
+ type: "session/subscribed",
30158
+ sessionId,
30159
+ lastSeq: projection.asOfSeq
30160
+ });
30161
+ if (record$3(projection.values).goal !== void 0) push({
30162
+ type: "session/projection",
30163
+ sessionId,
30164
+ key: "goal",
30165
+ value: record$3(projection.values).goal,
30166
+ seq: projection.asOfSeq
30167
+ });
30168
+ }
30169
+ })];
30170
+ try {
30171
+ while (!signal.aborted) {
30172
+ const next = frames.shift();
30173
+ if (next !== void 0) {
30174
+ bytes -= next.bytes;
30175
+ yield next.frame;
30176
+ } else await new Promise((resolve) => {
30177
+ wake = resolve;
30178
+ if (signal.aborted) notify();
30179
+ });
30180
+ }
30181
+ if (failure !== void 0) throw failure;
30182
+ } finally {
30183
+ controller.abort();
30184
+ off();
30185
+ signal.removeEventListener("abort", notify);
30186
+ await Promise.allSettled(tasks);
30187
+ for (const [id, item] of pending) if (item.signal === signal) pending.delete(id);
30188
+ }
30189
+ }
30190
+ return api;
30191
+ }
30192
+ //#endregion
30193
+ //#region src/dsh-remote/types.ts
30194
+ const DSH_REMOTE_PROTOCOL = "dsh.remote";
30195
+ const DSH_REMOTE_MAX_FRAME_BYTES = 60 * 1024;
30196
+ const DSH_REMOTE_MAX_PAGE_RESULT_BYTES = 40 * 1024;
29877
30197
  const MAX_PRESENTATION_DETAILS = 64 * 1024;
29878
30198
  const MAX_OPEN_CALL_SESSIONS = 128;
29879
30199
  const MAX_OPEN_CALLS_PER_SESSION = 512;
@@ -36301,10 +36621,11 @@ function apply(ctx, config) {
36301
36621
  tasks.dispose();
36302
36622
  }, "dsh-arkme: marketplace dynamic runner bridge");
36303
36623
  });
36304
- ctx.inject(["apiProxy"], (apiCtx) => {
36624
+ const attachRemoteApi = (apiCtx, publicApi) => {
36625
+ if (remoteHost !== void 0) return;
36305
36626
  const agentDefaultModel = apiCtx.get("agentDefaultModel");
36306
36627
  const sessionPersistence = apiCtx.get("sessionPersistence");
36307
- const apiProxy = new DshApiProxyAdapter(apiCtx.apiProxy, { ...typeof agentDefaultModel?.currentSelection !== "function" ? {} : { defaultModelSelection: () => agentDefaultModel.currentSelection() } });
36628
+ const apiProxy = new DshApiProxyAdapter(publicApi, { ...typeof agentDefaultModel?.currentSelection !== "function" ? {} : { defaultModelSelection: () => agentDefaultModel.currentSelection() } });
36308
36629
  service.accountScope.attachGuestConversationProbe(async () => {
36309
36630
  try {
36310
36631
  let cursor;
@@ -36416,6 +36737,22 @@ function apply(ctx, config) {
36416
36737
  await diagnostics.close();
36417
36738
  };
36418
36739
  }, "dsh-arkme: DSH remote Host lifecycle");
36740
+ };
36741
+ ctx.inject(["apiProxy"], (apiCtx) => {
36742
+ attachRemoteApi(apiCtx, apiCtx.apiProxy);
36743
+ });
36744
+ ctx.inject([
36745
+ "typertGateway",
36746
+ "sessionController",
36747
+ "workspaceController",
36748
+ "connection"
36749
+ ], (apiCtx) => {
36750
+ if (apiCtx.get("apiProxy") !== void 0) return;
36751
+ const lifetime = new AbortController();
36752
+ apiCtx.effect(() => () => {
36753
+ lifetime.abort();
36754
+ }, "arkme: DSH Gateway API lifetime");
36755
+ attachRemoteApi(apiCtx, createDshGatewayApi(apiCtx, apiCtx.get("typertGateway"), apiCtx.get("connection"), lifetime.signal));
36419
36756
  });
36420
36757
  const handler = createArkmeHostApi(service, {
36421
36758
  expectedPort: ctx.webServer.port,
@@ -36425,6 +36762,16 @@ function apply(ctx, config) {
36425
36762
  extensionInstallTasks: () => extensionInstallTasks,
36426
36763
  ownedExtensionInventory: () => ownedExtensionInventory,
36427
36764
  remoteHost: () => remoteHost,
36765
+ remoteUnavailableReason: () => {
36766
+ if (!config.dshRemoteFeatureEnabled) return "DSH 远控功能未启用";
36767
+ const missing = [
36768
+ "typertGateway",
36769
+ "sessionController",
36770
+ "workspaceController",
36771
+ "connection"
36772
+ ].filter((name) => ctx.get(name) === void 0);
36773
+ return ctx.get("apiProxy") === void 0 && missing.length > 0 ? `DSH 远控缺少服务:${missing.join(", ")}(旧版 apiProxy 也不可用)` : "DSH 远控 Host 正在初始化或初始化失败,请检查 Host 日志";
36774
+ },
36428
36775
  desktopQuarantine,
36429
36776
  openApiMcpController,
36430
36777
  teamService
@@ -1,2 +1,2 @@
1
- import { a as persistentArkmeExtensionActive, i as invokePersistentArkmeExtension, n as applyPersistentArkmeHostExtension, o as persistentArkmeExtensionRuntimeState, r as deactivatePersistentArkmeExtension, t as activatePersistentArkmeExtension } from "./persistent-runtime-Bsk6in2a.js";
1
+ import { a as persistentArkmeExtensionActive, i as invokePersistentArkmeExtension, n as applyPersistentArkmeHostExtension, o as persistentArkmeExtensionRuntimeState, r as deactivatePersistentArkmeExtension, t as activatePersistentArkmeExtension } from "./persistent-runtime-BnDj8qcY.js";
2
2
  export { activatePersistentArkmeExtension, applyPersistentArkmeHostExtension, deactivatePersistentArkmeExtension, invokePersistentArkmeExtension, persistentArkmeExtensionActive, persistentArkmeExtensionRuntimeState };