@cjhyy/code-shell-server 0.9.50 → 0.9.51

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.
@@ -1,7 +1,7 @@
1
1
  export { createPanelHttp } from "./panels/http.js";
2
2
  export * from "./panels/automations.js";
3
3
  export * from "./panels/hub-automations.js";
4
- export { createPanelManagement, PanelManagementError } from "./panels/management.js";
4
+ export { createPanelManagement, createPanelSnapshotReads, PanelManagementError, type PanelSnapshotReads, } from "./panels/management.js";
5
5
  export { createPanelRuntime, panelWebCompatibility } from "./panels/runtime.js";
6
6
  export { createHubPanelBinding } from "./panels/hub-binding.js";
7
7
  export * from "./panels/project-scope.js";
@@ -1,7 +1,7 @@
1
1
  export { createPanelHttp } from "./panels/http.js";
2
2
  export * from "./panels/automations.js";
3
3
  export * from "./panels/hub-automations.js";
4
- export { createPanelManagement, PanelManagementError } from "./panels/management.js";
4
+ export { createPanelManagement, createPanelSnapshotReads, PanelManagementError, } from "./panels/management.js";
5
5
  export { createPanelRuntime, panelWebCompatibility } from "./panels/runtime.js";
6
6
  export { createHubPanelBinding } from "./panels/hub-binding.js";
7
7
  export * from "./panels/project-scope.js";
@@ -17,7 +17,7 @@ export declare function createPanelHttp(options: PanelManagementHttpOptions & {
17
17
  authorizePanelDirectory?: PanelDirectoryAuthorizer;
18
18
  }): {
19
19
  service: {
20
- snapshot: (appId?: string) => Promise<import("./types.js").PanelSnapshot>;
20
+ snapshot: (appId?: string, reads?: import("./management.js").PanelSnapshotReads) => Promise<import("./types.js").PanelSnapshot>;
21
21
  packageHistory(context: import("./types.js").PanelOperationContext, id: unknown, expected: unknown): Promise<import("./types.js").PanelPackageHistory>;
22
22
  previewRestore(context: import("./types.js").PanelOperationContext, id: unknown, digest: unknown, expected: unknown): Promise<import("./types.js").PanelPackageRestoreReview>;
23
23
  cancelRestore(context: import("./types.js").PanelOperationContext, token: unknown): Promise<{
@@ -8,7 +8,7 @@ export interface PanelManagementHttpOptions extends PanelManagementOptions {
8
8
  /** Call only after the host's same-origin authentication boundary. */
9
9
  export declare function createPanelManagementHttp(options: PanelManagementHttpOptions): {
10
10
  service: {
11
- snapshot: (appId?: string) => Promise<import("./types.js").PanelSnapshot>;
11
+ snapshot: (appId?: string, reads?: import("./management.js").PanelSnapshotReads) => Promise<import("./types.js").PanelSnapshot>;
12
12
  packageHistory(context: PanelOperationContext, id: unknown, expected: unknown): Promise<import("./types.js").PanelPackageHistory>;
13
13
  previewRestore(context: PanelOperationContext, id: unknown, digest: unknown, expected: unknown): Promise<import("./types.js").PanelPackageRestoreReview>;
14
14
  cancelRestore(context: PanelOperationContext, token: unknown): Promise<{
@@ -1,5 +1,5 @@
1
1
  import { type PanelExecutionScope } from "./execution-gate.js";
2
- import { type PanelAppPreview, type PanelAppSourceInput } from "@cjhyy/code-shell-core";
2
+ import { type PanelAppInspectionReads, type PanelAppPreview, type PanelAppSourceInput } from "@cjhyy/code-shell-core";
3
3
  import type { PanelCompatibility, PanelDiscovery, PanelOperationContext, PanelReview, PanelProjectReview, PanelSnapshot, PanelPackageHistory, PanelPackageRestoreReview } from "./types.js";
4
4
  export declare class PanelManagementError extends Error {
5
5
  readonly status: number;
@@ -28,8 +28,17 @@ export interface PanelManagementOptions {
28
28
  repo: string;
29
29
  }, ref: string) => Promise<string>;
30
30
  }
31
+ /**
32
+ * Verified reads shared by the snapshots of one multi-project request, so the
33
+ * same package is not re-verified once per project. Create one per request.
34
+ */
35
+ export interface PanelSnapshotReads {
36
+ inspection: PanelAppInspectionReads;
37
+ digests: Map<string, Promise<string>>;
38
+ }
39
+ export declare function createPanelSnapshotReads(): PanelSnapshotReads;
31
40
  export declare function createPanelManagement(options: PanelManagementOptions): {
32
- snapshot: (appId?: string) => Promise<PanelSnapshot>;
41
+ snapshot: (appId?: string, reads?: PanelSnapshotReads) => Promise<PanelSnapshot>;
33
42
  packageHistory(context: PanelOperationContext, id: unknown, expected: unknown): Promise<PanelPackageHistory>;
34
43
  previewRestore(context: PanelOperationContext, id: unknown, digest: unknown, expected: unknown): Promise<PanelPackageRestoreReview>;
35
44
  cancelRestore(context: PanelOperationContext, token: unknown): Promise<{
@@ -3,7 +3,7 @@ import { panelPackageMutationMatches } from "./package-mutation.js";
3
3
  import { createHash, randomBytes } from "node:crypto";
4
4
  import { lstatSync, mkdirSync, statSync } from "node:fs";
5
5
  import { basename, extname, isAbsolute, join, resolve } from "node:path";
6
- import { SettingsManager, PanelAppAlreadyInstalledError, PanelAppInstallError, PanelAppReviewChangedError, assertSafePanelAppId, discoverGitPanelApps, installReviewedLocalPanelApp, invalidateSkillCache, listInstalledPanelApps, inspectProjectPanelApps, listRetainedPanelAppPackages, resolvePanelAppPackage, parsePanelAppPackagePins, currentPanelAppPackagePins, installedPanelAppUpdatedAt, retainInstalledPanelApp, userHome, panelAppsRoot, previewLocalPanelApp, resolveGitHubPanelAppCommit, resolvePanelAppBindingPolicy, uninstallPanelApp, } from "@cjhyy/code-shell-core";
6
+ import { SettingsManager, PanelAppAlreadyInstalledError, PanelAppInstallError, PanelAppReviewChangedError, assertSafePanelAppId, discoverGitPanelApps, installReviewedLocalPanelApp, invalidateSkillCache, listInstalledPanelApps, inspectProjectPanelApps, listRetainedPanelAppPackages, resolvePanelAppPackage, parsePanelAppPackagePins, currentPanelAppPackagePins, installedPanelAppUpdatedAt, retainInstalledPanelApp, userHome, panelAppsRoot, previewLocalPanelApp, inspectInstalledPanelAppDigest, resolveGitHubPanelAppCommit, resolvePanelAppBindingPolicy, uninstallPanelApp, } from "@cjhyy/code-shell-core";
7
7
  import { mutateJsonFile } from "@cjhyy/code-shell-core/internal";
8
8
  import { parseGithubUrl } from "@cjhyy/code-shell-core/internal/skills";
9
9
  const REVIEW_TTL = 8 * 60_000;
@@ -151,6 +151,9 @@ function assertRevision(revision) {
151
151
  if (typeof revision !== "string" || !/^[a-f0-9]{64}$/.test(revision))
152
152
  invalid();
153
153
  }
154
+ export function createPanelSnapshotReads() {
155
+ return { inspection: { packages: new Map() }, digests: new Map() };
156
+ }
154
157
  export function createPanelManagement(options) {
155
158
  const now = options.now ?? Date.now;
156
159
  const workspace = resolve(options.bindingCwd ?? options.cwd);
@@ -206,12 +209,17 @@ export function createPanelManagement(options) {
206
209
  const listApps = () => options.projectPackages
207
210
  ? inspectProjectPanelApps(workspace).then((result) => result.apps)
208
211
  : listInstalledPanelApps();
209
- async function inspectApp(app) {
212
+ async function inspectApp(app, reads) {
210
213
  const info = lstatSync(app.installPath);
211
214
  if (info.isSymbolicLink() || !info.isDirectory())
212
215
  throw new PanelManagementError(403, "unsafe_path", "面板安装目录不支持链接。");
213
- const preview = await previewLocalPanelApp({ kind: "dir", path: app.installPath });
214
- return { app, digest: preview.reviewToken };
216
+ // Same digest a dir preview reports, without re-hashing unchanged installed bytes.
217
+ let digest = reads?.digests.get(app.installPath);
218
+ if (!digest) {
219
+ digest = inspectInstalledPanelAppDigest(app.installPath);
220
+ reads?.digests.set(app.installPath, digest);
221
+ }
222
+ return { app, digest: await digest };
215
223
  }
216
224
  async function selectedApp(id) {
217
225
  const app = (await listApps()).find((item) => item.id === id);
@@ -240,12 +248,12 @@ export function createPanelManagement(options) {
240
248
  commit: SHA.test(parsed.source.ref ?? "") ? parsed.source.ref : "",
241
249
  };
242
250
  }
243
- async function snapshot(appId) {
251
+ async function snapshot(appId, reads) {
244
252
  if (appId !== undefined)
245
253
  assertSafePanelAppId(appId);
246
254
  options.assertBinding?.();
247
255
  const inspected = options.projectPackages
248
- ? await inspectProjectPanelApps(workspace, appId)
256
+ ? await inspectProjectPanelApps(workspace, appId, reads?.inspection)
249
257
  : undefined;
250
258
  const apps = inspected?.apps ?? (await listInstalledPanelApps(appId));
251
259
  options.assertBinding?.();
@@ -268,7 +276,7 @@ export function createPanelManagement(options) {
268
276
  .digest("hex"),
269
277
  }));
270
278
  for (const listed of apps) {
271
- const { app, digest } = await inspectApp(listed);
279
+ const { app, digest } = await inspectApp(listed, reads);
272
280
  const source = savedSource(app, saved);
273
281
  const { installPath: _path, source: _source, installedAt: _installedAt, lastUpdated: _lastUpdated, ...publicApp } = app;
274
282
  const support = compatibility(app);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cjhyy/code-shell-server",
3
- "version": "0.9.50",
3
+ "version": "0.9.51",
4
4
  "description": "CodeShell server transport layer — mobile remote HTTP/WS host, pairing, passcode gate, tunnel, rooms, uploads, and session/attachment services. Electron-free; precursor of the auth gateway.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -62,14 +62,14 @@
62
62
  "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\""
63
63
  },
64
64
  "dependencies": {
65
- "@cjhyy/code-shell-capability-coding": "0.9.50",
66
- "@cjhyy/code-shell-core": "0.9.50",
67
- "@cjhyy/code-shell-web": "0.9.50",
65
+ "@cjhyy/code-shell-capability-coding": "0.9.51",
66
+ "@cjhyy/code-shell-core": "0.9.51",
67
+ "@cjhyy/code-shell-web": "0.9.51",
68
68
  "@modelcontextprotocol/sdk": "^1.31.0",
69
69
  "@types/ws": "^8.18.1",
70
70
  "ws": "^8.21.0",
71
- "@cjhyy/code-shell-link": "0.9.50",
72
- "@cjhyy/code-shell-host": "0.9.50"
71
+ "@cjhyy/code-shell-link": "0.9.51",
72
+ "@cjhyy/code-shell-host": "0.9.51"
73
73
  },
74
74
  "engines": {
75
75
  "node": ">=20.10"