@cjhyy/code-shell-server 0.9.36 → 0.9.38
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/dist/bin/code-shell-cloud-account.d.ts +2 -0
- package/dist/bin/code-shell-cloud-account.js +53 -0
- package/dist/index.serve.d.ts +4 -0
- package/dist/index.serve.js +3 -0
- package/dist/panels/management.js +12 -1
- package/dist/panels/types.d.ts +5 -3
- package/dist/project-runtime/account-adoption.d.ts +34 -0
- package/dist/project-runtime/account-adoption.js +280 -0
- package/dist/project-runtime/account-binding.d.ts +18 -0
- package/dist/project-runtime/account-binding.js +42 -0
- package/dist/project-runtime/backup.d.ts +10 -0
- package/dist/project-runtime/backup.js +113 -20
- package/dist/project-runtime/cloud-account-auth.d.ts +23 -0
- package/dist/project-runtime/cloud-account-auth.js +287 -0
- package/dist/project-runtime/cloud-browser-auth.d.ts +15 -0
- package/dist/project-runtime/cloud-browser-auth.js +352 -0
- package/dist/project-runtime/control-authority.d.ts +46 -0
- package/dist/project-runtime/control-authority.js +15 -0
- package/dist/project-runtime/control-server.d.ts +17 -0
- package/dist/project-runtime/control-server.js +94 -26
- package/dist/project-runtime/docker-provider.d.ts +6 -0
- package/dist/project-runtime/docker-provider.js +10 -5
- package/dist/project-runtime/lock.js +181 -12
- package/dist/project-runtime/manager.d.ts +16 -8
- package/dist/project-runtime/manager.js +89 -15
- package/dist/project-runtime/proxy.d.ts +3 -3
- package/dist/project-runtime/proxy.js +15 -5
- package/dist/project-runtime/registry.d.ts +21 -1
- package/dist/project-runtime/registry.js +224 -6
- package/dist/serve/headless-server.js +14 -0
- package/package.json +7 -6
|
@@ -2,6 +2,7 @@ import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
|
2
2
|
import { constants, chmodSync, closeSync, existsSync, fstatSync, fsyncSync, lstatSync, mkdirSync, openSync, readSync, renameSync, rmSync, writeFileSync, } from "node:fs";
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
4
|
import { acquireProjectControllerLock } from "./lock.js";
|
|
5
|
+
import { CLOUD_ADOPTION_PENDING, isCloudAccountBinding, isCloudAccountOrigin, isCloudMultiAccountConfiguration, } from "./account-binding.js";
|
|
5
6
|
const UUID = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;
|
|
6
7
|
const TOKEN = /^[A-Za-z0-9_-]{43}$/;
|
|
7
8
|
const STATUSES = new Set(["stopped", "starting", "running", "stopping", "error"]);
|
|
@@ -58,9 +59,16 @@ export class ProjectRegistry {
|
|
|
58
59
|
controllerLock;
|
|
59
60
|
diskDigest;
|
|
60
61
|
markerEstablished = false;
|
|
62
|
+
storageFailed = false;
|
|
61
63
|
constructor(dataDir, now = Date.now, io = {}) {
|
|
62
64
|
this.now = now;
|
|
63
65
|
this.io = io;
|
|
66
|
+
if (this.io.multiAccountOrigin !== undefined &&
|
|
67
|
+
(!isCloudAccountOrigin(this.io.multiAccountOrigin) || this.io.offlineAccountAdoption))
|
|
68
|
+
throw new Error("Multi-account Cloud requires one explicit canonical Account origin.");
|
|
69
|
+
if (this.io.multiAccountOrigin &&
|
|
70
|
+
lstatSync(join(resolve(dataDir), "hub"), { throwIfNoEntry: false }))
|
|
71
|
+
throw new Error("Multi-account Cloud requires a fresh installation without legacy Hub authority.");
|
|
64
72
|
this.directory = resolve(dataDir, "project-control");
|
|
65
73
|
const existed = existsSync(this.directory);
|
|
66
74
|
mkdirSync(this.directory, { recursive: true, mode: 0o700 });
|
|
@@ -72,6 +80,16 @@ export class ProjectRegistry {
|
|
|
72
80
|
this.marker = join(this.directory, "initialized");
|
|
73
81
|
this.controllerLock = acquireProjectControllerLock(this.directory);
|
|
74
82
|
try {
|
|
83
|
+
if (!this.io.offlineAccountAdoption) {
|
|
84
|
+
try {
|
|
85
|
+
lstatSync(join(this.directory, CLOUD_ADOPTION_PENDING));
|
|
86
|
+
throw new Error("Cloud account adoption is incomplete; retry its explicit offline transaction.");
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
if (error.code !== "ENOENT")
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
75
93
|
if (existsSync(this.marker)) {
|
|
76
94
|
if (privateFileBytes(this.marker, 16).toString() !== "1\n")
|
|
77
95
|
throw new Error("Project initialization marker is corrupt.");
|
|
@@ -81,12 +99,26 @@ export class ProjectRegistry {
|
|
|
81
99
|
const bytes = privateFileBytes(this.file);
|
|
82
100
|
this.data = JSON.parse(bytes.toString("utf8"));
|
|
83
101
|
this.validate();
|
|
102
|
+
this.requireConfiguredMode();
|
|
84
103
|
this.diskDigest = digest(bytes);
|
|
85
104
|
}
|
|
86
105
|
else {
|
|
87
106
|
if (existsSync(this.marker) || existed)
|
|
88
107
|
throw new Error("Project registry is missing; restore the existing registry before starting");
|
|
89
|
-
this.data = {
|
|
108
|
+
this.data = {
|
|
109
|
+
version: this.io.multiAccountOrigin ? 3 : 1,
|
|
110
|
+
installationId: randomUUID(),
|
|
111
|
+
owners: [],
|
|
112
|
+
projects: [],
|
|
113
|
+
...(this.io.multiAccountOrigin
|
|
114
|
+
? {
|
|
115
|
+
multiAccount: {
|
|
116
|
+
accountOrigin: this.io.multiAccountOrigin,
|
|
117
|
+
managementEpoch: randomUUID(),
|
|
118
|
+
},
|
|
119
|
+
}
|
|
120
|
+
: {}),
|
|
121
|
+
};
|
|
90
122
|
this.write();
|
|
91
123
|
}
|
|
92
124
|
if (!this.markerEstablished) {
|
|
@@ -109,6 +141,10 @@ export class ProjectRegistry {
|
|
|
109
141
|
throw new Error("Stop all projects before restoring an installation.");
|
|
110
142
|
const next = structuredClone(this.data);
|
|
111
143
|
next.installationId = randomUUID();
|
|
144
|
+
if (next.accountBinding)
|
|
145
|
+
next.accountBinding.managementEpoch = randomUUID();
|
|
146
|
+
if (next.multiAccount)
|
|
147
|
+
next.multiAccount.managementEpoch = randomUUID();
|
|
112
148
|
for (const project of next.projects) {
|
|
113
149
|
if (project.generation > 0)
|
|
114
150
|
project.generation += 1;
|
|
@@ -122,19 +158,105 @@ export class ProjectRegistry {
|
|
|
122
158
|
this.assertStorage();
|
|
123
159
|
return this.data.installationId;
|
|
124
160
|
}
|
|
161
|
+
get accountBinding() {
|
|
162
|
+
this.assertStorage();
|
|
163
|
+
return this.data.accountBinding && { ...this.data.accountBinding };
|
|
164
|
+
}
|
|
165
|
+
get multiAccount() {
|
|
166
|
+
this.assertStorage();
|
|
167
|
+
return this.data.multiAccount && { ...this.data.multiAccount };
|
|
168
|
+
}
|
|
169
|
+
/** Called only after trusted authority verification, never with browser-selected identity. */
|
|
170
|
+
ensureAccountOwner(accountOrigin, accountId) {
|
|
171
|
+
this.assertStorage();
|
|
172
|
+
if (this.data.version !== 3 ||
|
|
173
|
+
accountOrigin !== this.data.multiAccount?.accountOrigin ||
|
|
174
|
+
typeof accountId !== "string" ||
|
|
175
|
+
!UUID.test(accountId))
|
|
176
|
+
throw new ProjectRegistryError(403, "此账号没有工作台权限。");
|
|
177
|
+
const existing = this.data.owners.find((owner) => "accountId" in owner &&
|
|
178
|
+
owner.accountOrigin === accountOrigin &&
|
|
179
|
+
owner.accountId === accountId);
|
|
180
|
+
if (existing)
|
|
181
|
+
return existing.id;
|
|
182
|
+
if (this.data.owners.length >= 128)
|
|
183
|
+
throw new ProjectRegistryError(429, "工作台账号数量已达到上限。");
|
|
184
|
+
const next = structuredClone(this.data), ownerId = randomUUID();
|
|
185
|
+
next.owners.push({ id: ownerId, accountOrigin, accountId });
|
|
186
|
+
this.write(next);
|
|
187
|
+
this.data = next;
|
|
188
|
+
return ownerId;
|
|
189
|
+
}
|
|
190
|
+
requireConfiguredMode() {
|
|
191
|
+
if (this.data.version === 3) {
|
|
192
|
+
if (this.io.multiAccountOrigin !== this.data.multiAccount?.accountOrigin)
|
|
193
|
+
throw new Error("Multi-account Cloud requires its configured Account origin; automatic mode adoption is refused.");
|
|
194
|
+
}
|
|
195
|
+
else if (this.io.multiAccountOrigin !== undefined) {
|
|
196
|
+
throw new Error("Multi-account Cloud requires a fresh installation; legacy adoption is refused.");
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/** Offline migration only; the caller must durably preserve source evidence first. */
|
|
200
|
+
bindAccount(binding) {
|
|
201
|
+
this.assertStorage();
|
|
202
|
+
if (this.data.version !== 1 ||
|
|
203
|
+
this.data.accountBinding !== undefined ||
|
|
204
|
+
!isCloudAccountBinding(binding) ||
|
|
205
|
+
this.data.owners.length !== 1 ||
|
|
206
|
+
this.data.owners[0].id !== binding.ownerId ||
|
|
207
|
+
this.data.projects.some((project) => project.status !== "stopped"))
|
|
208
|
+
throw new Error("Cloud adoption requires one explicit legacy owner and stopped projects.");
|
|
209
|
+
const next = structuredClone(this.data);
|
|
210
|
+
// The real historical registry rejects version 2. Unknown metadata alone
|
|
211
|
+
// cannot prevent an old controller from continuing its username authority.
|
|
212
|
+
next.version = 2;
|
|
213
|
+
next.accountBinding = { ...binding };
|
|
214
|
+
this.write(next);
|
|
215
|
+
this.data = next;
|
|
216
|
+
}
|
|
125
217
|
validate(data = this.data) {
|
|
126
218
|
if (!data ||
|
|
127
|
-
data.version
|
|
219
|
+
![1, 2, 3].includes(data.version) ||
|
|
128
220
|
!UUID.test(data.installationId) ||
|
|
129
221
|
!Array.isArray(data.owners) ||
|
|
130
222
|
!Array.isArray(data.projects) ||
|
|
131
223
|
data.owners.length > 128 ||
|
|
132
224
|
data.projects.length > 128)
|
|
133
225
|
throw new Error("Project registry is corrupt; restore its backup");
|
|
226
|
+
if ((data.version !== 3 && data.multiAccount !== undefined) ||
|
|
227
|
+
(data.version === 1 && data.accountBinding !== undefined) ||
|
|
228
|
+
(data.version === 2 &&
|
|
229
|
+
(!isCloudAccountBinding(data.accountBinding) ||
|
|
230
|
+
data.owners.length !== 1 ||
|
|
231
|
+
data.owners[0]?.id !== data.accountBinding.ownerId)) ||
|
|
232
|
+
(data.version === 3 &&
|
|
233
|
+
(data.accountBinding !== undefined ||
|
|
234
|
+
!isCloudMultiAccountConfiguration(data.multiAccount) ||
|
|
235
|
+
typeof data.installationId !== "string" ||
|
|
236
|
+
Object.keys(data).sort().join() !==
|
|
237
|
+
"installationId,multiAccount,owners,projects,version")))
|
|
238
|
+
throw new Error("Cloud account ownership is missing or corrupt; restore its backup.");
|
|
134
239
|
const owners = new Set();
|
|
135
240
|
const names = new Set();
|
|
136
241
|
for (const owner of data.owners) {
|
|
242
|
+
if (data.version === 3) {
|
|
243
|
+
if (!owner ||
|
|
244
|
+
typeof owner.id !== "string" ||
|
|
245
|
+
!UUID.test(owner.id) ||
|
|
246
|
+
owners.has(owner.id) ||
|
|
247
|
+
!("accountId" in owner) ||
|
|
248
|
+
Object.keys(owner).sort().join() !== "accountId,accountOrigin,id" ||
|
|
249
|
+
owner.accountOrigin !== data.multiAccount.accountOrigin ||
|
|
250
|
+
typeof owner.accountId !== "string" ||
|
|
251
|
+
!UUID.test(owner.accountId) ||
|
|
252
|
+
names.has(owner.accountId))
|
|
253
|
+
throw new Error("Project account owner registry is corrupt");
|
|
254
|
+
owners.add(owner.id);
|
|
255
|
+
names.add(owner.accountId);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
137
258
|
if (!owner ||
|
|
259
|
+
!("username" in owner) ||
|
|
138
260
|
!UUID.test(owner.id) ||
|
|
139
261
|
typeof owner.username !== "string" ||
|
|
140
262
|
!owner.username.trim() ||
|
|
@@ -149,6 +271,27 @@ export class ProjectRegistry {
|
|
|
149
271
|
}
|
|
150
272
|
const ids = new Set();
|
|
151
273
|
for (const project of data.projects) {
|
|
274
|
+
if (data.version === 3 &&
|
|
275
|
+
(!project ||
|
|
276
|
+
typeof project.id !== "string" ||
|
|
277
|
+
typeof project.ownerId !== "string" ||
|
|
278
|
+
typeof project.runtimePassword !== "string" ||
|
|
279
|
+
Object.keys(project).sort().join() !==
|
|
280
|
+
[
|
|
281
|
+
"id",
|
|
282
|
+
"ownerId",
|
|
283
|
+
"generation",
|
|
284
|
+
"runtimeUsername",
|
|
285
|
+
"runtimePassword",
|
|
286
|
+
"name",
|
|
287
|
+
"status",
|
|
288
|
+
"createdAt",
|
|
289
|
+
"updatedAt",
|
|
290
|
+
...(project.error === undefined ? [] : ["error"]),
|
|
291
|
+
]
|
|
292
|
+
.sort()
|
|
293
|
+
.join()))
|
|
294
|
+
throw new Error("Project account runtime registry is corrupt");
|
|
152
295
|
if (!project ||
|
|
153
296
|
!UUID.test(project.id) ||
|
|
154
297
|
ids.has(project.id) ||
|
|
@@ -174,6 +317,8 @@ export class ProjectRegistry {
|
|
|
174
317
|
}
|
|
175
318
|
}
|
|
176
319
|
assertStorage() {
|
|
320
|
+
if (this.storageFailed)
|
|
321
|
+
throw new Error("Project registry durability failed; restart and diagnose before continuing.");
|
|
177
322
|
this.controllerLock.assertHeld();
|
|
178
323
|
if (this.markerEstablished && privateFileBytes(this.marker, 16).toString() !== "1\n")
|
|
179
324
|
throw new Error("Project initialization marker changed.");
|
|
@@ -192,15 +337,29 @@ export class ProjectRegistry {
|
|
|
192
337
|
throw new Error("Project registry is too large.");
|
|
193
338
|
const file = join(this.directory, `.registry-${randomUUID()}.tmp`);
|
|
194
339
|
let fd;
|
|
340
|
+
let committed = false;
|
|
195
341
|
try {
|
|
196
342
|
fd = openSync(file, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW ?? 0), 0o600);
|
|
197
343
|
writeFileSync(fd, bytes);
|
|
198
|
-
fsyncSync(fd);
|
|
344
|
+
(this.io.fsync ?? fsyncSync)(fd);
|
|
199
345
|
closeSync(fd);
|
|
200
346
|
fd = undefined;
|
|
201
347
|
this.assertStorage();
|
|
202
348
|
(this.io.rename ?? renameSync)(file, this.file);
|
|
349
|
+
committed = true;
|
|
203
350
|
this.diskDigest = digest(bytes);
|
|
351
|
+
const directory = openSync(this.directory, constants.O_RDONLY);
|
|
352
|
+
try {
|
|
353
|
+
(this.io.fsync ?? fsyncSync)(directory);
|
|
354
|
+
}
|
|
355
|
+
finally {
|
|
356
|
+
closeSync(directory);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
catch (error) {
|
|
360
|
+
if (committed)
|
|
361
|
+
this.storageFailed = true;
|
|
362
|
+
throw error;
|
|
204
363
|
}
|
|
205
364
|
finally {
|
|
206
365
|
if (fd !== undefined)
|
|
@@ -214,12 +373,14 @@ export class ProjectRegistry {
|
|
|
214
373
|
}
|
|
215
374
|
list(username) {
|
|
216
375
|
this.assertStorage();
|
|
217
|
-
|
|
376
|
+
this.requireLegacy();
|
|
377
|
+
const owner = this.data.owners.find((item) => "username" in item && item.username === username);
|
|
218
378
|
return this.data.projects.filter((item) => item.ownerId === owner?.id).map(projectView);
|
|
219
379
|
}
|
|
220
380
|
get(username, id) {
|
|
221
381
|
this.assertStorage();
|
|
222
|
-
|
|
382
|
+
this.requireLegacy();
|
|
383
|
+
const owner = this.data.owners.find((item) => "username" in item && item.username === username);
|
|
223
384
|
const project = this.data.projects.find((item) => item.id === id && item.ownerId === owner?.id);
|
|
224
385
|
if (!project)
|
|
225
386
|
throw new ProjectRegistryError(404, "找不到这个项目。");
|
|
@@ -227,6 +388,39 @@ export class ProjectRegistry {
|
|
|
227
388
|
}
|
|
228
389
|
create(username, name) {
|
|
229
390
|
this.assertStorage();
|
|
391
|
+
this.requireLegacy();
|
|
392
|
+
return this.createForOwner(username, name);
|
|
393
|
+
}
|
|
394
|
+
listAccount(ownerId) {
|
|
395
|
+
this.requireAccountOwner(ownerId);
|
|
396
|
+
return this.data.projects.filter((item) => item.ownerId === ownerId).map(projectView);
|
|
397
|
+
}
|
|
398
|
+
getAccount(ownerId, id) {
|
|
399
|
+
this.requireAccountOwner(ownerId);
|
|
400
|
+
const project = this.data.projects.find((item) => item.id === id && item.ownerId === ownerId);
|
|
401
|
+
if (!project)
|
|
402
|
+
throw new ProjectRegistryError(404, "找不到这个项目。");
|
|
403
|
+
return { ...project };
|
|
404
|
+
}
|
|
405
|
+
createAccount(ownerId, name) {
|
|
406
|
+
this.requireAccountOwner(ownerId);
|
|
407
|
+
if (this.data.version === 3)
|
|
408
|
+
return this.createForAccountOwner(ownerId, name);
|
|
409
|
+
// This username is internal legacy metadata, never the Account display name.
|
|
410
|
+
return this.createForOwner(this.data.owners[0].username, name);
|
|
411
|
+
}
|
|
412
|
+
requireLegacy() {
|
|
413
|
+
if (this.data.version !== 1)
|
|
414
|
+
throw new ProjectRegistryError(403, "此 Cloud 已采用明确的账号归属,请通过云账号管理。");
|
|
415
|
+
}
|
|
416
|
+
requireAccountOwner(ownerId) {
|
|
417
|
+
this.assertStorage();
|
|
418
|
+
if ((this.data.version === 2 && this.data.accountBinding?.ownerId === ownerId) ||
|
|
419
|
+
(this.data.version === 3 && this.data.owners.some((owner) => owner.id === ownerId)))
|
|
420
|
+
return;
|
|
421
|
+
throw new ProjectRegistryError(403, "此账号没有 Cloud 管理权限。");
|
|
422
|
+
}
|
|
423
|
+
createForOwner(username, name) {
|
|
230
424
|
if (typeof name !== "string" ||
|
|
231
425
|
!name.trim() ||
|
|
232
426
|
name.trim().length > 80 ||
|
|
@@ -241,7 +435,7 @@ export class ProjectRegistry {
|
|
|
241
435
|
if (this.data.projects.length >= 32)
|
|
242
436
|
throw new ProjectRegistryError(429, "项目数量已达到上限(32 个)。");
|
|
243
437
|
const next = structuredClone(this.data);
|
|
244
|
-
let owner = next.owners.find((item) => item.username === username);
|
|
438
|
+
let owner = next.owners.find((item) => "username" in item && item.username === username);
|
|
245
439
|
if (!owner) {
|
|
246
440
|
owner = { id: randomUUID(), username };
|
|
247
441
|
next.owners.push(owner);
|
|
@@ -263,6 +457,30 @@ export class ProjectRegistry {
|
|
|
263
457
|
this.data = next;
|
|
264
458
|
return { ...project };
|
|
265
459
|
}
|
|
460
|
+
createForAccountOwner(ownerId, name) {
|
|
461
|
+
if (typeof name !== "string" ||
|
|
462
|
+
!name.trim() ||
|
|
463
|
+
name.trim().length > 80 ||
|
|
464
|
+
/[\x00-\x1f\x7f]/.test(name))
|
|
465
|
+
throw new ProjectRegistryError(400, "请输入 1 至 80 个字符的项目名称。");
|
|
466
|
+
if (this.data.projects.length >= 128)
|
|
467
|
+
throw new ProjectRegistryError(429, "工作台项目数量已达到上限(128 个)。");
|
|
468
|
+
const next = structuredClone(this.data), timestamp = this.now(), project = {
|
|
469
|
+
id: randomUUID(),
|
|
470
|
+
ownerId,
|
|
471
|
+
name: name.trim(),
|
|
472
|
+
status: "stopped",
|
|
473
|
+
generation: 0,
|
|
474
|
+
runtimeUsername: "project-runtime",
|
|
475
|
+
runtimePassword: randomBytes(32).toString("base64url"),
|
|
476
|
+
createdAt: timestamp,
|
|
477
|
+
updatedAt: timestamp,
|
|
478
|
+
};
|
|
479
|
+
next.projects.push(project);
|
|
480
|
+
this.write(next);
|
|
481
|
+
this.data = next;
|
|
482
|
+
return { ...project };
|
|
483
|
+
}
|
|
266
484
|
update(id, patch) {
|
|
267
485
|
this.assertStorage();
|
|
268
486
|
const index = this.data.projects.findIndex((item) => item.id === id);
|
|
@@ -594,6 +594,20 @@ export async function startHeadlessServer(opts) {
|
|
|
594
594
|
hubJson(res, 200, { status: "ok", mode: hubAuth ? "hub" : "passcode" });
|
|
595
595
|
return;
|
|
596
596
|
}
|
|
597
|
+
// The public shell probes this before login. A standalone workspace has no
|
|
598
|
+
// Cloud browser authority; an explicit miss selects its existing Hub gate.
|
|
599
|
+
if (pathname === "/api/v1/cloud-browser/capabilities") {
|
|
600
|
+
if (req.url !== pathname) {
|
|
601
|
+
hubJson(res, 400, { error: "request parameters are not supported" });
|
|
602
|
+
}
|
|
603
|
+
else if (req.method !== "GET") {
|
|
604
|
+
hubJson(res, 405, { error: "method not allowed" });
|
|
605
|
+
}
|
|
606
|
+
else {
|
|
607
|
+
hubJson(res, 404, { error: "API endpoint not found" });
|
|
608
|
+
}
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
597
611
|
if (hubAuth) {
|
|
598
612
|
if (await links?.handlePublic(req, res))
|
|
599
613
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cjhyy/code-shell-server",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.38",
|
|
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",
|
|
@@ -49,7 +49,8 @@
|
|
|
49
49
|
},
|
|
50
50
|
"bin": {
|
|
51
51
|
"code-shell-serve": "./dist/bin/code-shell-serve.js",
|
|
52
|
-
"code-shell-settings-recovery": "./dist/bin/code-shell-settings-recovery.js"
|
|
52
|
+
"code-shell-settings-recovery": "./dist/bin/code-shell-settings-recovery.js",
|
|
53
|
+
"code-shell-cloud-account": "./dist/bin/code-shell-cloud-account.js"
|
|
53
54
|
},
|
|
54
55
|
"files": [
|
|
55
56
|
"dist"
|
|
@@ -60,13 +61,13 @@
|
|
|
60
61
|
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\""
|
|
61
62
|
},
|
|
62
63
|
"dependencies": {
|
|
63
|
-
"@cjhyy/code-shell-capability-coding": "0.9.
|
|
64
|
-
"@cjhyy/code-shell-core": "0.9.
|
|
65
|
-
"@cjhyy/code-shell-web": "0.9.
|
|
64
|
+
"@cjhyy/code-shell-capability-coding": "0.9.38",
|
|
65
|
+
"@cjhyy/code-shell-core": "0.9.38",
|
|
66
|
+
"@cjhyy/code-shell-web": "0.9.38",
|
|
66
67
|
"@modelcontextprotocol/sdk": "^1.31.0",
|
|
67
68
|
"@types/ws": "^8.18.1",
|
|
68
69
|
"ws": "^8.21.0",
|
|
69
|
-
"@cjhyy/code-shell-link": "0.9.
|
|
70
|
+
"@cjhyy/code-shell-link": "0.9.38"
|
|
70
71
|
},
|
|
71
72
|
"engines": {
|
|
72
73
|
"node": ">=20.10"
|