@ours.network/cowork 0.3.5 → 0.3.7-nightly.20260815.80ea770
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/README.md +6 -6
- package/dist/cli.js +161 -11
- package/dist/daemon.js +782 -1317
- package/dist/web/assets/app.js +10 -10
- package/docs/01-prerequisites.md +1 -1
- package/docs/02-installation.md +1 -1
- package/docs/05-room-workflow.md +2 -2
- package/docs/06-invites.md +2 -0
- package/docs/07-messaging-history.md +2 -2
- package/docs/08-backup-restore.md +2 -2
- package/docs/09-service-management.md +1 -1
- package/docs/10-limitations.md +3 -2
- package/docs/11-web-console.md +1 -1
- package/package.json +3 -6
- package/dist/mufl_code/BBAE58CF78DEE59692F456EAFFA9A6109835B66846FC3989F6D201B8F4523A55.muflo +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ours-cowork
|
|
2
2
|
|
|
3
|
-
`ours-cowork` is a standalone daemon for durable ours mission rooms. It owns one ordinary
|
|
3
|
+
`ours-cowork` is a standalone standard-SDK daemon for durable ours mission rooms. It owns one ordinary ours identity per room through an embedded `@ours.network/sdk` runtime, an ordered local archive, a private Unix management socket, and a localhost web console with room RPC.
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
6
|
ours-cowork web
|
|
@@ -9,7 +9,7 @@ ours-cowork docs
|
|
|
9
9
|
|
|
10
10
|
`ours-cowork web` starts the daemon if it is absent, waits for the console, and opens `http://127.0.0.1:3052/`. Create a room with a friendly display name first, then add each invitation requirement from its Invite panel. Names are trimmed, normalized to Unicode NFC, and may contain 1–64 Unicode characters excluding control and format characters. Duplicate names are allowed. The Communication view contains the human-readable room chat; operational records remain in Events and the complete ordered stream remains in Archive.
|
|
11
11
|
|
|
12
|
-
The friendly `room_name` is presentation metadata. New rooms
|
|
12
|
+
The friendly `room_name` is presentation metadata. New rooms use the globally unique SDK identity `ours-cowork-<room_id>`; that authenticated name is independent of later display-name changes. Duplicate display names are allowed because identity CIDs and room IDs, not names, are the authorization and routing keys. Pre-1.0 rooms using `cowork-room-<room_id>` or `ours-cowork-room:<name>` custom packet state are detected and refused: back them up with the old release, recreate them, and re-invite their participants.
|
|
13
13
|
|
|
14
14
|
The localhost HTTP console has no authentication. Keep it bound to `127.0.0.1`; do not proxy, forward, or expose the port to other hosts. Room state is refreshed by periodic polling, not pushed to the browser.
|
|
15
15
|
|
|
@@ -17,13 +17,13 @@ The package runs independently with its own config and state directory. Operator
|
|
|
17
17
|
|
|
18
18
|
Ordinary ours-mcp identities can join only as remote participants over the ours protocol.
|
|
19
19
|
|
|
20
|
-
Active participants can also send files through the room
|
|
21
|
-
them as opaque bytes, archives them before consuming
|
|
22
|
-
|
|
20
|
+
Active participants can also send files through the room identity. Cowork treats
|
|
21
|
+
them as opaque bytes, archives them before consuming SDK inbox state, and relays an
|
|
22
|
+
SDK-authenticated metadata envelope plus the binary file to every other active seat.
|
|
23
23
|
Files are limited to 2 MiB; larger inputs fail loudly instead of weakening
|
|
24
24
|
crash recovery guarantees.
|
|
25
25
|
|
|
26
|
-
The release package contains the standalone daemon, operator CLI,
|
|
26
|
+
The release package contains the standalone daemon, operator CLI, deterministic web assets, and all eleven offline operator topics. Standard identity, messaging, reply, file, and lifecycle behavior comes from the public `@ours.network/sdk`; no custom MUFL room actor is shipped.
|
|
27
27
|
|
|
28
28
|
Licensed under [FSL-1.1-Apache-2.0](./LICENSE).
|
|
29
29
|
|
package/dist/cli.js
CHANGED
|
@@ -4277,6 +4277,7 @@ var MAX_TEXT_BYTES = 262144;
|
|
|
4277
4277
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
4278
4278
|
var MAX_HISTORY_PAGE_BYTES = 3 * 1024 * 1024;
|
|
4279
4279
|
var MAX_MANAGEMENT_RESPONSE_BYTES = MAX_HISTORY_PAGE_BYTES + 1024 * 1024;
|
|
4280
|
+
var MAX_EXTERNAL_INVITE_BYTES = 48 * 1024;
|
|
4280
4281
|
var MAX_FILE_NAME_BYTES = 255;
|
|
4281
4282
|
var MAX_MIME_BYTES = 255;
|
|
4282
4283
|
var MAX_ROLE_BYTES = 256;
|
|
@@ -4327,9 +4328,9 @@ var RoomNameSchema = external_exports.string().refine(
|
|
|
4327
4328
|
});
|
|
4328
4329
|
}
|
|
4329
4330
|
});
|
|
4330
|
-
var ROOM_IDENTITY_PREFIX = "ours-cowork-
|
|
4331
|
-
function roomIdentityName(
|
|
4332
|
-
return `${ROOM_IDENTITY_PREFIX}${
|
|
4331
|
+
var ROOM_IDENTITY_PREFIX = "ours-cowork-";
|
|
4332
|
+
function roomIdentityName(roomId) {
|
|
4333
|
+
return `${ROOM_IDENTITY_PREFIX}${LowerCrockfordUlidSchema.parse(roomId)}`;
|
|
4333
4334
|
}
|
|
4334
4335
|
function legacyRoomIdentityName(roomId) {
|
|
4335
4336
|
return `cowork-room-${LowerCrockfordUlidSchema.parse(roomId)}`;
|
|
@@ -4343,7 +4344,7 @@ var FileMimeSchema = external_exports.string().refine(
|
|
|
4343
4344
|
`file MIME metadata must be at most ${MAX_MIME_BYTES} UTF-8 bytes`
|
|
4344
4345
|
);
|
|
4345
4346
|
var RoomStateSchema = external_exports.enum(["provisioning", "active", "closing", "closed"]);
|
|
4346
|
-
var SeatStateSchema = external_exports.enum(["active", "removed"]);
|
|
4347
|
+
var SeatStateSchema = external_exports.enum(["pending", "active", "removed"]);
|
|
4347
4348
|
var InviteModeSchema = external_exports.enum(["one_time", "public"]);
|
|
4348
4349
|
var InviteStateSchema = external_exports.enum([
|
|
4349
4350
|
"live",
|
|
@@ -4365,7 +4366,9 @@ var SeatSchema = external_exports.object({
|
|
|
4365
4366
|
display_name: NonEmptyStringSchema,
|
|
4366
4367
|
role: RoleSchema,
|
|
4367
4368
|
invite_id: NonEmptyStringSchema,
|
|
4368
|
-
accepted_at: Rfc3339Schema,
|
|
4369
|
+
accepted_at: Rfc3339Schema.optional(),
|
|
4370
|
+
requested_at: Rfc3339Schema.optional(),
|
|
4371
|
+
invite_sha256: external_exports.string().regex(/^[0-9a-f]{64}$/).optional(),
|
|
4369
4372
|
participant_id: LowerCrockfordUlidSchema,
|
|
4370
4373
|
state: SeatStateSchema,
|
|
4371
4374
|
alias: NonEmptyStringSchema.optional(),
|
|
@@ -4374,7 +4377,25 @@ var SeatSchema = external_exports.object({
|
|
|
4374
4377
|
replaces_seat: LowerCrockfordUlidSchema.optional(),
|
|
4375
4378
|
bounced_at: Rfc3339Schema.optional()
|
|
4376
4379
|
}).strict().superRefine((seat, context) => {
|
|
4377
|
-
if (seat.state === "
|
|
4380
|
+
if (seat.state === "pending") {
|
|
4381
|
+
for (const field of ["requested_at", "invite_sha256"]) {
|
|
4382
|
+
if (seat[field] === void 0) {
|
|
4383
|
+
context.addIssue({ code: external_exports.ZodIssueCode.custom, path: [field], message: `pending seats require ${field}` });
|
|
4384
|
+
}
|
|
4385
|
+
}
|
|
4386
|
+
for (const field of ["accepted_at", "removed_at", "removed_epoch", "bounced_at"]) {
|
|
4387
|
+
if (seat[field] !== void 0) {
|
|
4388
|
+
context.addIssue({ code: external_exports.ZodIssueCode.custom, path: [field], message: `${field} is forbidden on pending seats` });
|
|
4389
|
+
}
|
|
4390
|
+
}
|
|
4391
|
+
} else if (seat.state === "removed") {
|
|
4392
|
+
if (seat.accepted_at === void 0 && seat.requested_at === void 0) {
|
|
4393
|
+
context.addIssue({
|
|
4394
|
+
code: external_exports.ZodIssueCode.custom,
|
|
4395
|
+
path: ["accepted_at"],
|
|
4396
|
+
message: "removed seats require accepted_at unless they are cancelled external admissions"
|
|
4397
|
+
});
|
|
4398
|
+
}
|
|
4378
4399
|
if (seat.removed_at === void 0) {
|
|
4379
4400
|
context.addIssue({
|
|
4380
4401
|
code: external_exports.ZodIssueCode.custom,
|
|
@@ -4390,6 +4411,9 @@ var SeatSchema = external_exports.object({
|
|
|
4390
4411
|
});
|
|
4391
4412
|
}
|
|
4392
4413
|
} else {
|
|
4414
|
+
if (seat.accepted_at === void 0) {
|
|
4415
|
+
context.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["accepted_at"], message: "active seats require accepted_at" });
|
|
4416
|
+
}
|
|
4393
4417
|
for (const field of ["removed_at", "removed_epoch", "bounced_at"]) {
|
|
4394
4418
|
if (seat[field] !== void 0) {
|
|
4395
4419
|
context.addIssue({
|
|
@@ -4400,6 +4424,13 @@ var SeatSchema = external_exports.object({
|
|
|
4400
4424
|
}
|
|
4401
4425
|
}
|
|
4402
4426
|
}
|
|
4427
|
+
if (seat.requested_at === void 0 !== (seat.invite_sha256 === void 0)) {
|
|
4428
|
+
context.addIssue({
|
|
4429
|
+
code: external_exports.ZodIssueCode.custom,
|
|
4430
|
+
path: ["invite_sha256"],
|
|
4431
|
+
message: "external admission metadata requires both requested_at and invite_sha256"
|
|
4432
|
+
});
|
|
4433
|
+
}
|
|
4403
4434
|
});
|
|
4404
4435
|
var RoomInviteSchema = external_exports.object({
|
|
4405
4436
|
invite_id: NonEmptyStringSchema,
|
|
@@ -4479,7 +4510,7 @@ var RoleBriefingSchema = external_exports.object({
|
|
|
4479
4510
|
}).strict();
|
|
4480
4511
|
function refineRoomLineage(room, context) {
|
|
4481
4512
|
const pendingIdentityName = legacyRoomIdentityName(room.room_id);
|
|
4482
|
-
const currentPendingIdentityName =
|
|
4513
|
+
const currentPendingIdentityName = roomIdentityName(room.room_id);
|
|
4483
4514
|
const exactPacketPending = room.state === "provisioning" && room.status === "packet_pending" && (room.identity_name === pendingIdentityName || room.identity_name === currentPendingIdentityName) && room.invites.length === 0 && room.seats.length === 0 && room.activated_at === void 0 && room.closed_at === void 0;
|
|
4484
4515
|
if (room.identity_cid === "" && !exactPacketPending) {
|
|
4485
4516
|
context.addIssue({
|
|
@@ -4558,6 +4589,7 @@ var CurrentRoomSchema = external_exports.object({
|
|
|
4558
4589
|
refineRoomLineage(room, context);
|
|
4559
4590
|
const byParticipant = /* @__PURE__ */ new Map();
|
|
4560
4591
|
const activeAliases = /* @__PURE__ */ new Set();
|
|
4592
|
+
const authorizedCids = /* @__PURE__ */ new Set();
|
|
4561
4593
|
for (const [index, seat] of room.seats.entries()) {
|
|
4562
4594
|
if (byParticipant.has(seat.participant_id)) {
|
|
4563
4595
|
context.addIssue({
|
|
@@ -4567,6 +4599,16 @@ var CurrentRoomSchema = external_exports.object({
|
|
|
4567
4599
|
});
|
|
4568
4600
|
}
|
|
4569
4601
|
byParticipant.set(seat.participant_id, seat);
|
|
4602
|
+
if (seat.state === "pending" || seat.state === "active") {
|
|
4603
|
+
if (authorizedCids.has(seat.identity)) {
|
|
4604
|
+
context.addIssue({
|
|
4605
|
+
code: external_exports.ZodIssueCode.custom,
|
|
4606
|
+
path: ["seats", index, "identity"],
|
|
4607
|
+
message: "at most one pending or active seat may exist per CID"
|
|
4608
|
+
});
|
|
4609
|
+
}
|
|
4610
|
+
authorizedCids.add(seat.identity);
|
|
4611
|
+
}
|
|
4570
4612
|
if (room.anonymous && seat.alias === void 0) {
|
|
4571
4613
|
context.addIssue({
|
|
4572
4614
|
code: external_exports.ZodIssueCode.custom,
|
|
@@ -4659,6 +4701,16 @@ var RoleBriefingDeleteInputSchema = external_exports.object({
|
|
|
4659
4701
|
var PostMessageInputSchema = external_exports.object({
|
|
4660
4702
|
text: MessageTextSchema
|
|
4661
4703
|
}).strict();
|
|
4704
|
+
var ContainerIdSchema = external_exports.string().regex(/^[0-9a-f]{64}$/i, "must be a 64-character hexadecimal CID").transform((value) => value.toUpperCase());
|
|
4705
|
+
var AcceptExternalInviteInputSchema = external_exports.object({
|
|
4706
|
+
role: RoleSchema,
|
|
4707
|
+
invite: external_exports.string().refine(
|
|
4708
|
+
(value) => Buffer.byteLength(value, "utf8") <= MAX_EXTERNAL_INVITE_BYTES,
|
|
4709
|
+
`invite input must be at most ${MAX_EXTERNAL_INVITE_BYTES} UTF-8 bytes`
|
|
4710
|
+
),
|
|
4711
|
+
expected_cid: ContainerIdSchema.optional(),
|
|
4712
|
+
replaces_seat: LowerCrockfordUlidSchema.optional()
|
|
4713
|
+
}).strict();
|
|
4662
4714
|
var AuthorSnapshotSchema = external_exports.object({
|
|
4663
4715
|
identity: NonEmptyStringSchema,
|
|
4664
4716
|
display_name: NonEmptyStringSchema,
|
|
@@ -4686,6 +4738,10 @@ var AuthorAliasSchema = external_exports.object({
|
|
|
4686
4738
|
participant_id: LowerCrockfordUlidSchema,
|
|
4687
4739
|
alias: NonEmptyStringSchema
|
|
4688
4740
|
}).strict();
|
|
4741
|
+
var ReplyReferenceSchema = external_exports.object({
|
|
4742
|
+
wire_id: NonEmptyStringSchema,
|
|
4743
|
+
sentence: PositiveSafeIntegerSchema.optional()
|
|
4744
|
+
}).strict();
|
|
4689
4745
|
var MessageShape = {
|
|
4690
4746
|
kind: external_exports.literal("message"),
|
|
4691
4747
|
message_id: LowerCrockfordUlidSchema,
|
|
@@ -4710,7 +4766,8 @@ var MessageShape = {
|
|
|
4710
4766
|
}
|
|
4711
4767
|
}),
|
|
4712
4768
|
source_msg_id: external_exports.number().int().nonnegative().safe().optional(),
|
|
4713
|
-
source_wire_id: NonEmptyStringSchema.optional()
|
|
4769
|
+
source_wire_id: NonEmptyStringSchema.optional(),
|
|
4770
|
+
source_reply_to: ReplyReferenceSchema.optional()
|
|
4714
4771
|
};
|
|
4715
4772
|
var RelayIntentShape = {
|
|
4716
4773
|
kind: external_exports.literal("relay_intent"),
|
|
@@ -4753,7 +4810,8 @@ var FileShape = {
|
|
|
4753
4810
|
}
|
|
4754
4811
|
}),
|
|
4755
4812
|
source_file_id: external_exports.number().int().nonnegative().safe(),
|
|
4756
|
-
source_wire_id: NonEmptyStringSchema.optional()
|
|
4813
|
+
source_wire_id: NonEmptyStringSchema.optional(),
|
|
4814
|
+
source_reply_to: ReplyReferenceSchema.optional()
|
|
4757
4815
|
};
|
|
4758
4816
|
var MembershipIntentShape = {
|
|
4759
4817
|
kind: external_exports.literal("membership_intent"),
|
|
@@ -4932,6 +4990,7 @@ var RpcTransportError = class extends CliError {
|
|
|
4932
4990
|
var NATIVE_MUTATION_METHODS = /* @__PURE__ */ new Set([
|
|
4933
4991
|
"room.create",
|
|
4934
4992
|
"room.invite",
|
|
4993
|
+
"room.accept",
|
|
4935
4994
|
"room.revoke",
|
|
4936
4995
|
"room.message",
|
|
4937
4996
|
"room.close",
|
|
@@ -4975,6 +5034,7 @@ Room commands:
|
|
|
4975
5034
|
settings <room-id> [--name <display-name>] [--goal <text>] [--briefing <text>] [--status <text>] [--quiet-membership true|false]
|
|
4976
5035
|
role-briefing <room-id> --role <label> (--text <text> | --delete)
|
|
4977
5036
|
invite <room-id> [--role <label>] [--mode one_time|public] [--min-accepts <n>]
|
|
5037
|
+
accept <room-id> --role <label> (--invite-file <path> | --invite-stdin) [--expected-cid <64-hex>] [--replaces <participant-id>]
|
|
4978
5038
|
revoke <room-id> <invite-id>
|
|
4979
5039
|
remove <room-id> <participant> [--silent]
|
|
4980
5040
|
replace <room-id> <participant> [--mode one_time|public] [--min-accepts <n>] [--silent]
|
|
@@ -5057,7 +5117,7 @@ function loadCliConfig() {
|
|
|
5057
5117
|
throw new CliError(EXIT.internal, "internal", error instanceof Error ? error.message : "failed to load config", { cause: error });
|
|
5058
5118
|
}
|
|
5059
5119
|
}
|
|
5060
|
-
function roomRequest(command, args) {
|
|
5120
|
+
async function roomRequest(command, args) {
|
|
5061
5121
|
if (!command) usageError("room requires a command");
|
|
5062
5122
|
switch (command) {
|
|
5063
5123
|
case "create": {
|
|
@@ -5115,6 +5175,27 @@ function roomRequest(command, args) {
|
|
|
5115
5175
|
min_accepts: minimum
|
|
5116
5176
|
} };
|
|
5117
5177
|
}
|
|
5178
|
+
case "accept": {
|
|
5179
|
+
const parsed = parseOptions(
|
|
5180
|
+
args,
|
|
5181
|
+
["--role", "--invite-file", "--expected-cid", "--replaces"],
|
|
5182
|
+
["--invite-stdin"]
|
|
5183
|
+
);
|
|
5184
|
+
const [roomId] = exactPositionals(parsed, 1, "room accept");
|
|
5185
|
+
const inviteFile = parsed.values["--invite-file"];
|
|
5186
|
+
const inviteStdin = parsed.booleans.has("--invite-stdin");
|
|
5187
|
+
if ((inviteFile === void 0 ? 0 : 1) + (inviteStdin ? 1 : 0) !== 1) {
|
|
5188
|
+
usageError("room accept requires exactly one of --invite-file or --invite-stdin");
|
|
5189
|
+
}
|
|
5190
|
+
const invite = inviteFile === void 0 ? await readBoundedStdin() : readSecureInviteFile(inviteFile);
|
|
5191
|
+
return { method: "room.accept", params: {
|
|
5192
|
+
room_id: roomId,
|
|
5193
|
+
role: requiredFlag(parsed, "--role", "room accept"),
|
|
5194
|
+
invite,
|
|
5195
|
+
...parsed.values["--expected-cid"] === void 0 ? {} : { expected_cid: parsed.values["--expected-cid"] },
|
|
5196
|
+
...parsed.values["--replaces"] === void 0 ? {} : { replaces_seat: parsed.values["--replaces"] }
|
|
5197
|
+
} };
|
|
5198
|
+
}
|
|
5118
5199
|
case "remove": {
|
|
5119
5200
|
const parsed = parseOptions(args, [], ["--silent"]);
|
|
5120
5201
|
const [roomId, participant] = exactPositionals(parsed, 2, "room remove");
|
|
@@ -5197,6 +5278,75 @@ function roomRequest(command, args) {
|
|
|
5197
5278
|
usageError(`unknown room command: ${command}`);
|
|
5198
5279
|
}
|
|
5199
5280
|
}
|
|
5281
|
+
function readSecureInviteFile(path) {
|
|
5282
|
+
const noFollow = fs.constants.O_NOFOLLOW ?? 0;
|
|
5283
|
+
let fd;
|
|
5284
|
+
try {
|
|
5285
|
+
const observed = fs.lstatSync(path);
|
|
5286
|
+
if (observed.isSymbolicLink() || !observed.isFile() || observed.nlink !== 1 || (observed.mode & 511) !== 384 || typeof process.getuid === "function" && observed.uid !== process.getuid()) {
|
|
5287
|
+
throw new Error("invite file must be an owned 0600 single-link regular file");
|
|
5288
|
+
}
|
|
5289
|
+
if (observed.size > MAX_EXTERNAL_INVITE_BYTES) throw new Error("invite input exceeds 48 KiB");
|
|
5290
|
+
fd = fs.openSync(path, fs.constants.O_RDONLY | noFollow);
|
|
5291
|
+
const opened = fs.fstatSync(fd);
|
|
5292
|
+
const current = fs.lstatSync(path);
|
|
5293
|
+
if (!opened.isFile() || opened.nlink !== 1 || (opened.mode & 511) !== 384 || typeof process.getuid === "function" && opened.uid !== process.getuid() || current.isSymbolicLink() || current.dev !== opened.dev || current.ino !== opened.ino) {
|
|
5294
|
+
throw new Error("invite file changed while opening");
|
|
5295
|
+
}
|
|
5296
|
+
const bytes = fs.readFileSync(fd);
|
|
5297
|
+
if (bytes.length > MAX_EXTERNAL_INVITE_BYTES) throw new Error("invite input exceeds 48 KiB");
|
|
5298
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
5299
|
+
} catch (error) {
|
|
5300
|
+
throw new CliError(
|
|
5301
|
+
EXIT.invalidState,
|
|
5302
|
+
"invalid_params",
|
|
5303
|
+
error instanceof Error && /48 KiB/.test(error.message) ? "invite input exceeds 48 KiB" : "invite file is unavailable or insecure"
|
|
5304
|
+
);
|
|
5305
|
+
} finally {
|
|
5306
|
+
if (fd !== void 0) fs.closeSync(fd);
|
|
5307
|
+
}
|
|
5308
|
+
}
|
|
5309
|
+
function readBoundedStdin() {
|
|
5310
|
+
return new Promise((resolveInput, rejectInput) => {
|
|
5311
|
+
const chunks = [];
|
|
5312
|
+
let size = 0;
|
|
5313
|
+
const fail = () => {
|
|
5314
|
+
cleanup();
|
|
5315
|
+
process.stdin.pause();
|
|
5316
|
+
rejectInput(new CliError(EXIT.invalidState, "invalid_params", "invite input exceeds 48 KiB"));
|
|
5317
|
+
};
|
|
5318
|
+
const cleanup = () => {
|
|
5319
|
+
process.stdin.off("data", onData);
|
|
5320
|
+
process.stdin.off("end", onEnd);
|
|
5321
|
+
process.stdin.off("error", onError);
|
|
5322
|
+
};
|
|
5323
|
+
const onData = (chunk) => {
|
|
5324
|
+
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
5325
|
+
size += bytes.length;
|
|
5326
|
+
if (size > MAX_EXTERNAL_INVITE_BYTES) {
|
|
5327
|
+
fail();
|
|
5328
|
+
return;
|
|
5329
|
+
}
|
|
5330
|
+
chunks.push(bytes);
|
|
5331
|
+
};
|
|
5332
|
+
const onEnd = () => {
|
|
5333
|
+
cleanup();
|
|
5334
|
+
try {
|
|
5335
|
+
resolveInput(new TextDecoder("utf-8", { fatal: true }).decode(Buffer.concat(chunks)));
|
|
5336
|
+
} catch {
|
|
5337
|
+
rejectInput(new CliError(EXIT.invalidState, "invalid_params", "invite input is not valid UTF-8"));
|
|
5338
|
+
}
|
|
5339
|
+
};
|
|
5340
|
+
const onError = () => {
|
|
5341
|
+
cleanup();
|
|
5342
|
+
rejectInput(new CliError(EXIT.invalidState, "invalid_params", "could not read invite input"));
|
|
5343
|
+
};
|
|
5344
|
+
process.stdin.on("data", onData);
|
|
5345
|
+
process.stdin.once("end", onEnd);
|
|
5346
|
+
process.stdin.once("error", onError);
|
|
5347
|
+
process.stdin.resume();
|
|
5348
|
+
});
|
|
5349
|
+
}
|
|
5200
5350
|
function rpcCall(socketPath, method, params, timeoutMs = RPC_TIMEOUT_MS) {
|
|
5201
5351
|
const id = `${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
5202
5352
|
const request = `${JSON.stringify({ version: 1, id, method, params })}
|
|
@@ -5656,7 +5806,7 @@ async function execute(args, output) {
|
|
|
5656
5806
|
return;
|
|
5657
5807
|
}
|
|
5658
5808
|
if (command === "room") {
|
|
5659
|
-
const request = roomRequest(args[1], args.slice(2));
|
|
5809
|
+
const request = await roomRequest(args[1], args.slice(2));
|
|
5660
5810
|
const config2 = loadCliConfig();
|
|
5661
5811
|
const socketPath = join2(config2.stateDir, "management.sock");
|
|
5662
5812
|
const result = request.method === "room.history" ? await readHistoryPages(socketPath, request.params) : await rpcCall(
|