@ours.network/cowork 1.1.4 → 1.3.0
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 +3 -0
- package/dist/cli.js +232 -14
- package/dist/daemon.js +1053 -177
- package/dist/web/assets/app.js +9 -9
- package/docs/05-room-workflow.md +80 -2
- package/docs/07-messaging-history.md +9 -3
- package/docs/08-backup-restore.md +1 -1
- package/docs/10-limitations.md +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,6 +23,8 @@ The package keeps room metadata and a per-room indexed `archive.sqlite3` in its
|
|
|
23
23
|
|
|
24
24
|
Ordinary ours-mcp identities can join only as remote participants over the ours protocol.
|
|
25
25
|
|
|
26
|
+
Granted room members can create message-only scoped reply threads for an explicit subset of stable room participant IDs through the generic Ours command catalog's `start_thread` command. Selected members receive separate root copies and reply with the SDK's native `reply_to_wire_id`; Cowork maps each descendant to the recipient's local immediate-parent copy. The selected participant-ID/CID pairs are immutable, later members are not backfilled, and excluded members receive no scoped message, file notice, notification, participant-history row, command result, or routing metadata. A message without `reply_to_wire_id` remains an ordinary whole-room message. See [Room workflow](./docs/05-room-workflow.md#scoped-reply-threads) for command discovery, schema, errors, and retry behavior, and [Messaging and history](./docs/07-messaging-history.md#reply-threading) for reply and history semantics.
|
|
27
|
+
|
|
26
28
|
Active participants can also send files through the room identity. Cowork treats
|
|
27
29
|
them as opaque bytes, archives them before consuming SDK inbox state, and relays an
|
|
28
30
|
SDK-authenticated metadata envelope plus the binary file to every other active seat.
|
|
@@ -42,3 +44,4 @@ ours-cowork docs web
|
|
|
42
44
|
|
|
43
45
|
Before production use, read the limitations topic. In particular, backups require a stopped daemon and restore uses the complete state directory.
|
|
44
46
|
Lost room identity leases are recovered automatically with a non-force bind and exact persisted-CID proof. Operators can invoke the same safe path explicitly with `ours-cowork room rebind <room-id>`; it never recreates an established identity or steals a live lease.
|
|
47
|
+
The localhost host-management CLI/API and web Archive retain full scoped-thread visibility for administrators, including excluded-member traffic that participant APIs hide. Runtime `room.history` is an authenticated, grant-gated participant view with viewer-local cursors; host cursors and participant cursors are not interchangeable. The shared SDK history remains local to each identity and does not define Cowork routing or host archive retention.
|
package/dist/cli.js
CHANGED
|
@@ -4351,11 +4351,85 @@ var SHARED_ROOM_COMMANDS = [
|
|
|
4351
4351
|
"room.role.rest.remove"
|
|
4352
4352
|
];
|
|
4353
4353
|
var RUNTIME_COMMAND_NAMES = [
|
|
4354
|
+
"start_thread",
|
|
4354
4355
|
"list-members",
|
|
4355
4356
|
"remove-member",
|
|
4356
4357
|
...SHARED_ROOM_COMMANDS
|
|
4357
4358
|
];
|
|
4358
4359
|
|
|
4360
|
+
// src/thread-contracts.ts
|
|
4361
|
+
var ParticipantIdSchema = external_exports.string().regex(
|
|
4362
|
+
/^[0-7][0-9a-hjkmnp-tv-z]{25}$/,
|
|
4363
|
+
"must be a 26-character lowercase Crockford ULID"
|
|
4364
|
+
);
|
|
4365
|
+
var ContainerIdSchema = external_exports.string().regex(/^[0-9a-f]{64}$/i, "must be a 64-character hexadecimal CID").transform((value) => value.toUpperCase());
|
|
4366
|
+
var TopicTextSchema = external_exports.string().refine(
|
|
4367
|
+
(value) => Array.from(value).length >= 1 && Array.from(value).length <= 120 && value.trim().length > 0 && !/[\p{Cc}\p{Cf}]/u.test(value),
|
|
4368
|
+
"topic must contain 1-120 Unicode characters without control or format characters"
|
|
4369
|
+
);
|
|
4370
|
+
var InputTopicSchema = TopicTextSchema.transform((value) => value.trim());
|
|
4371
|
+
var StoredTopicSchema = TopicTextSchema.refine(
|
|
4372
|
+
(value) => value === value.trim(),
|
|
4373
|
+
"stored topic must already be trimmed"
|
|
4374
|
+
);
|
|
4375
|
+
var IdempotencyKeySchema = external_exports.string().regex(
|
|
4376
|
+
/^[A-Za-z0-9._:-]{1,128}$/,
|
|
4377
|
+
"must contain 1-128 portable idempotency-key characters"
|
|
4378
|
+
);
|
|
4379
|
+
var ThreadMemberSchema = external_exports.object({
|
|
4380
|
+
participant_id: ParticipantIdSchema,
|
|
4381
|
+
identity: ContainerIdSchema
|
|
4382
|
+
}).strict();
|
|
4383
|
+
var ThreadRootSchema = external_exports.object({
|
|
4384
|
+
schema_version: external_exports.literal(1),
|
|
4385
|
+
thread_id: ParticipantIdSchema,
|
|
4386
|
+
topic: StoredTopicSchema,
|
|
4387
|
+
creator_participant_id: ParticipantIdSchema,
|
|
4388
|
+
members: external_exports.array(ThreadMemberSchema).min(1),
|
|
4389
|
+
idempotency_key: IdempotencyKeySchema,
|
|
4390
|
+
fingerprint: external_exports.string().regex(/^[0-9a-f]{64}$/, "must be a lowercase SHA-256 digest")
|
|
4391
|
+
}).strict().superRefine((root, context) => {
|
|
4392
|
+
const participantIds = /* @__PURE__ */ new Set();
|
|
4393
|
+
const identities = /* @__PURE__ */ new Set();
|
|
4394
|
+
for (const [index, member] of root.members.entries()) {
|
|
4395
|
+
if (participantIds.has(member.participant_id)) {
|
|
4396
|
+
context.addIssue({
|
|
4397
|
+
code: external_exports.ZodIssueCode.custom,
|
|
4398
|
+
path: ["members", index, "participant_id"],
|
|
4399
|
+
message: "thread member participant IDs must be unique"
|
|
4400
|
+
});
|
|
4401
|
+
}
|
|
4402
|
+
participantIds.add(member.participant_id);
|
|
4403
|
+
if (identities.has(member.identity)) {
|
|
4404
|
+
context.addIssue({
|
|
4405
|
+
code: external_exports.ZodIssueCode.custom,
|
|
4406
|
+
path: ["members", index, "identity"],
|
|
4407
|
+
message: "thread member identities must be unique"
|
|
4408
|
+
});
|
|
4409
|
+
}
|
|
4410
|
+
identities.add(member.identity);
|
|
4411
|
+
}
|
|
4412
|
+
if (!participantIds.has(root.creator_participant_id)) {
|
|
4413
|
+
context.addIssue({
|
|
4414
|
+
code: external_exports.ZodIssueCode.custom,
|
|
4415
|
+
path: ["creator_participant_id"],
|
|
4416
|
+
message: "thread creator must be a member"
|
|
4417
|
+
});
|
|
4418
|
+
}
|
|
4419
|
+
});
|
|
4420
|
+
var ThreadScopeSchema = external_exports.object({
|
|
4421
|
+
thread_id: ParticipantIdSchema,
|
|
4422
|
+
parent_key: external_exports.string().regex(
|
|
4423
|
+
/^(?:message|file):[0-7][0-9a-hjkmnp-tv-z]{25}$/,
|
|
4424
|
+
"must identify an immediate message or file parent"
|
|
4425
|
+
).optional()
|
|
4426
|
+
}).strict();
|
|
4427
|
+
var StartThreadInputSchema = external_exports.object({
|
|
4428
|
+
topic: InputTopicSchema,
|
|
4429
|
+
participant_ids: external_exports.array(ParticipantIdSchema).min(1),
|
|
4430
|
+
idempotency_key: IdempotencyKeySchema
|
|
4431
|
+
}).strict();
|
|
4432
|
+
|
|
4359
4433
|
// src/contracts.ts
|
|
4360
4434
|
var MAX_TEXT_BYTES = 262144;
|
|
4361
4435
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
@@ -4379,11 +4453,17 @@ var LowerCrockfordUlidSchema = external_exports.string().regex(
|
|
|
4379
4453
|
/^[0-7][0-9a-hjkmnp-tv-z]{25}$/,
|
|
4380
4454
|
"must be a 26-character lowercase Crockford ULID"
|
|
4381
4455
|
);
|
|
4382
|
-
var
|
|
4456
|
+
var ContainerIdSchema2 = external_exports.string().regex(/^[0-9a-f]{64}$/i, "must be a 64-character hexadecimal CID").transform((value) => value.toUpperCase());
|
|
4383
4457
|
var RuntimeCommandNameSchema = external_exports.union([external_exports.enum(RUNTIME_COMMAND_NAMES), ConsumerCommandNameSchema]);
|
|
4458
|
+
var RuntimeCommandNamespacePatternSchema = external_exports.string().max(128).regex(/^(?:[a-z0-9][a-z0-9-]*\.)+\*$/);
|
|
4459
|
+
var RuntimeCommandGrantPatternSchema = external_exports.union([
|
|
4460
|
+
RuntimeCommandNameSchema,
|
|
4461
|
+
external_exports.literal("*"),
|
|
4462
|
+
RuntimeCommandNamespacePatternSchema
|
|
4463
|
+
]);
|
|
4384
4464
|
var RuntimeCommandGrantSchema = external_exports.object({
|
|
4385
|
-
caller_cid:
|
|
4386
|
-
command:
|
|
4465
|
+
caller_cid: ContainerIdSchema2,
|
|
4466
|
+
command: RuntimeCommandGrantPatternSchema
|
|
4387
4467
|
}).strict();
|
|
4388
4468
|
function isStrictRfc3339(value) {
|
|
4389
4469
|
const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|[+-](\d{2}):(\d{2}))$/.exec(value);
|
|
@@ -4432,7 +4512,7 @@ var RoleSchema = utf8Bounded("role", MAX_ROLE_BYTES);
|
|
|
4432
4512
|
var ROOM_ROLE = "room";
|
|
4433
4513
|
var RuntimeRoleCommandGrantSchema = external_exports.object({
|
|
4434
4514
|
role: RoleSchema,
|
|
4435
|
-
commands: external_exports.array(
|
|
4515
|
+
commands: external_exports.array(RuntimeCommandGrantPatternSchema).superRefine((commands, context) => {
|
|
4436
4516
|
const seen = /* @__PURE__ */ new Set();
|
|
4437
4517
|
for (const [index, command] of commands.entries()) {
|
|
4438
4518
|
if (seen.has(command)) {
|
|
@@ -4727,7 +4807,7 @@ var CurrentRoomSchema = external_exports.object({
|
|
|
4727
4807
|
lifecycle_request: external_exports.object({
|
|
4728
4808
|
request_id: external_exports.string().min(1).max(256),
|
|
4729
4809
|
command: external_exports.enum(["room.close", "room.delete"]),
|
|
4730
|
-
caller_cid:
|
|
4810
|
+
caller_cid: ContainerIdSchema2,
|
|
4731
4811
|
accepted_at: Rfc3339Schema,
|
|
4732
4812
|
state: external_exports.enum(["pending", "failed", "completed"]),
|
|
4733
4813
|
error: external_exports.literal("lifecycle_failed").optional()
|
|
@@ -4881,7 +4961,7 @@ var AcceptExternalInviteInputSchema = external_exports.object({
|
|
|
4881
4961
|
(value) => Buffer.byteLength(value, "utf8") <= MAX_EXTERNAL_INVITE_BYTES,
|
|
4882
4962
|
`invite input must be at most ${MAX_EXTERNAL_INVITE_BYTES} UTF-8 bytes`
|
|
4883
4963
|
),
|
|
4884
|
-
expected_cid:
|
|
4964
|
+
expected_cid: ContainerIdSchema2.optional()
|
|
4885
4965
|
}).strict();
|
|
4886
4966
|
var ListMembersCommandInputSchema = external_exports.object({}).strict();
|
|
4887
4967
|
var CommandIdempotencyKeySchema = external_exports.string().regex(
|
|
@@ -4956,7 +5036,9 @@ var MessageShape = {
|
|
|
4956
5036
|
}),
|
|
4957
5037
|
source_msg_id: external_exports.number().int().nonnegative().safe().optional(),
|
|
4958
5038
|
source_wire_id: NonEmptyStringSchema.optional(),
|
|
4959
|
-
source_reply_to: ReplyReferenceSchema.optional()
|
|
5039
|
+
source_reply_to: ReplyReferenceSchema.optional(),
|
|
5040
|
+
scope: ThreadScopeSchema.optional(),
|
|
5041
|
+
thread_root: ThreadRootSchema.optional()
|
|
4960
5042
|
};
|
|
4961
5043
|
var RelayIntentShape = {
|
|
4962
5044
|
kind: external_exports.literal("relay_intent"),
|
|
@@ -4964,7 +5046,12 @@ var RelayIntentShape = {
|
|
|
4964
5046
|
file_id: LowerCrockfordUlidSchema.optional(),
|
|
4965
5047
|
recipient_identity: NonEmptyStringSchema
|
|
4966
5048
|
};
|
|
4967
|
-
var RelayResultStatusSchema = external_exports.enum([
|
|
5049
|
+
var RelayResultStatusSchema = external_exports.enum([
|
|
5050
|
+
"queued",
|
|
5051
|
+
"send_failed",
|
|
5052
|
+
"skipped_removed",
|
|
5053
|
+
"skipped_reply_unavailable"
|
|
5054
|
+
]);
|
|
4968
5055
|
var RelayResultShape = {
|
|
4969
5056
|
kind: external_exports.literal("relay_result"),
|
|
4970
5057
|
intent_record_id: NonEmptyStringSchema,
|
|
@@ -5002,6 +5089,18 @@ var FileShape = {
|
|
|
5002
5089
|
source_wire_id: NonEmptyStringSchema.optional(),
|
|
5003
5090
|
source_reply_to: ReplyReferenceSchema.optional()
|
|
5004
5091
|
};
|
|
5092
|
+
var IntakeRejectionShape = {
|
|
5093
|
+
kind: external_exports.literal("intake_rejection"),
|
|
5094
|
+
source_kind: external_exports.enum(["message", "file"]),
|
|
5095
|
+
source_msg_id: external_exports.number().int().nonnegative().safe().optional(),
|
|
5096
|
+
source_file_id: external_exports.number().int().nonnegative().safe().optional(),
|
|
5097
|
+
source_wire_id: NonEmptyStringSchema,
|
|
5098
|
+
sender_identity: NonEmptyStringSchema,
|
|
5099
|
+
sender_participant_id: LowerCrockfordUlidSchema,
|
|
5100
|
+
fingerprint: external_exports.string().regex(/^[0-9a-f]{64}$/),
|
|
5101
|
+
error: external_exports.enum(["reply_target_unavailable", "thread_files_unsupported"]),
|
|
5102
|
+
notification_attempt_claimed: external_exports.literal(true)
|
|
5103
|
+
};
|
|
5005
5104
|
var MembershipIntentShape = {
|
|
5006
5105
|
kind: external_exports.literal("membership_intent"),
|
|
5007
5106
|
action: external_exports.enum(["remove"]),
|
|
@@ -5039,6 +5138,7 @@ var MessageRecordSchema = external_exports.object({ ...RecordCommonShape, ...Mes
|
|
|
5039
5138
|
var FileRecordSchema = external_exports.object({ ...RecordCommonShape, ...FileShape }).strict();
|
|
5040
5139
|
var RelayIntentRecordSchema = external_exports.object({ ...RecordCommonShape, ...RelayIntentShape }).strict();
|
|
5041
5140
|
var RelayResultRecordSchema = external_exports.object({ ...RecordCommonShape, ...RelayResultShape }).strict();
|
|
5141
|
+
var IntakeRejectionRecordSchema = external_exports.object({ ...RecordCommonShape, ...IntakeRejectionShape }).strict();
|
|
5042
5142
|
var MembershipIntentRecordSchema = external_exports.object({ ...RecordCommonShape, ...MembershipIntentShape }).strict();
|
|
5043
5143
|
var MembershipResultRecordSchema = external_exports.object({ ...RecordCommonShape, ...MembershipResultShape }).strict();
|
|
5044
5144
|
var CloseNoticeIntentRecordSchema = external_exports.object({ ...RecordCommonShape, ...CloseNoticeIntentShape }).strict();
|
|
@@ -5048,6 +5148,7 @@ var RawCommunicationRecordSchema = external_exports.discriminatedUnion("kind", [
|
|
|
5048
5148
|
FileRecordSchema,
|
|
5049
5149
|
RelayIntentRecordSchema,
|
|
5050
5150
|
RelayResultRecordSchema,
|
|
5151
|
+
IntakeRejectionRecordSchema,
|
|
5051
5152
|
MembershipIntentRecordSchema,
|
|
5052
5153
|
MembershipResultRecordSchema,
|
|
5053
5154
|
CloseNoticeIntentRecordSchema,
|
|
@@ -5063,6 +5164,18 @@ function refineRelaySubject(record, context) {
|
|
|
5063
5164
|
});
|
|
5064
5165
|
}
|
|
5065
5166
|
}
|
|
5167
|
+
function refineIntakeRejection(record, context) {
|
|
5168
|
+
if (record.kind !== "intake_rejection") return;
|
|
5169
|
+
const hasMessage = record.source_msg_id !== void 0;
|
|
5170
|
+
const hasFile = record.source_file_id !== void 0;
|
|
5171
|
+
if (hasMessage === hasFile || (record.source_kind === "message" ? !hasMessage : !hasFile)) {
|
|
5172
|
+
context.addIssue({
|
|
5173
|
+
code: external_exports.ZodIssueCode.custom,
|
|
5174
|
+
path: ["source_kind"],
|
|
5175
|
+
message: "intake rejections require exactly one numeric source field matching source_kind"
|
|
5176
|
+
});
|
|
5177
|
+
}
|
|
5178
|
+
}
|
|
5066
5179
|
function refineFileRecord(record, context) {
|
|
5067
5180
|
if (record.kind !== "file" || record.data_base64 === void 0) return;
|
|
5068
5181
|
const bytes = Buffer.from(record.data_base64, "base64");
|
|
@@ -5113,6 +5226,102 @@ function refineMessageCategory(message, context) {
|
|
|
5113
5226
|
}
|
|
5114
5227
|
}
|
|
5115
5228
|
}
|
|
5229
|
+
function refineMessageThread(message, context) {
|
|
5230
|
+
if (message.thread_root !== void 0) {
|
|
5231
|
+
if (message.scope === void 0) {
|
|
5232
|
+
context.addIssue({
|
|
5233
|
+
code: external_exports.ZodIssueCode.custom,
|
|
5234
|
+
path: ["scope"],
|
|
5235
|
+
message: "thread root messages require scope"
|
|
5236
|
+
});
|
|
5237
|
+
return;
|
|
5238
|
+
}
|
|
5239
|
+
if (message.scope.thread_id !== message.message_id || message.thread_root.thread_id !== message.message_id) {
|
|
5240
|
+
context.addIssue({
|
|
5241
|
+
code: external_exports.ZodIssueCode.custom,
|
|
5242
|
+
path: ["thread_root", "thread_id"],
|
|
5243
|
+
message: "thread root thread_id and scope thread_id must equal message_id"
|
|
5244
|
+
});
|
|
5245
|
+
}
|
|
5246
|
+
if (message.scope.parent_key !== void 0) {
|
|
5247
|
+
context.addIssue({
|
|
5248
|
+
code: external_exports.ZodIssueCode.custom,
|
|
5249
|
+
path: ["scope", "parent_key"],
|
|
5250
|
+
message: "parent_key is forbidden on thread root messages"
|
|
5251
|
+
});
|
|
5252
|
+
}
|
|
5253
|
+
if (message.category !== "chat") {
|
|
5254
|
+
context.addIssue({
|
|
5255
|
+
code: external_exports.ZodIssueCode.custom,
|
|
5256
|
+
path: ["category"],
|
|
5257
|
+
message: "thread root messages must be chat messages"
|
|
5258
|
+
});
|
|
5259
|
+
}
|
|
5260
|
+
if (message.text !== `Thread: ${message.thread_root.topic}`) {
|
|
5261
|
+
context.addIssue({
|
|
5262
|
+
code: external_exports.ZodIssueCode.custom,
|
|
5263
|
+
path: ["text"],
|
|
5264
|
+
message: "thread root message text must identify its topic"
|
|
5265
|
+
});
|
|
5266
|
+
}
|
|
5267
|
+
const creator = message.thread_root.members.find(
|
|
5268
|
+
(member) => member.participant_id === message.thread_root?.creator_participant_id
|
|
5269
|
+
);
|
|
5270
|
+
if (creator?.identity !== message.author.identity) {
|
|
5271
|
+
context.addIssue({
|
|
5272
|
+
code: external_exports.ZodIssueCode.custom,
|
|
5273
|
+
path: ["thread_root", "creator_participant_id"],
|
|
5274
|
+
message: "thread root creator must match the message author"
|
|
5275
|
+
});
|
|
5276
|
+
}
|
|
5277
|
+
if (message.author_alias !== void 0 && message.author_alias.participant_id !== message.thread_root.creator_participant_id) {
|
|
5278
|
+
context.addIssue({
|
|
5279
|
+
code: external_exports.ZodIssueCode.custom,
|
|
5280
|
+
path: ["author_alias", "participant_id"],
|
|
5281
|
+
message: "thread root author alias must identify the creator"
|
|
5282
|
+
});
|
|
5283
|
+
}
|
|
5284
|
+
for (const field of ["source_msg_id", "source_wire_id", "source_reply_to"]) {
|
|
5285
|
+
if (message[field] !== void 0) {
|
|
5286
|
+
context.addIssue({
|
|
5287
|
+
code: external_exports.ZodIssueCode.custom,
|
|
5288
|
+
path: [field],
|
|
5289
|
+
message: `${field} is forbidden on thread root messages`
|
|
5290
|
+
});
|
|
5291
|
+
}
|
|
5292
|
+
}
|
|
5293
|
+
return;
|
|
5294
|
+
}
|
|
5295
|
+
if (message.scope === void 0) return;
|
|
5296
|
+
if (message.scope.parent_key === void 0) {
|
|
5297
|
+
context.addIssue({
|
|
5298
|
+
code: external_exports.ZodIssueCode.custom,
|
|
5299
|
+
path: ["scope", "parent_key"],
|
|
5300
|
+
message: "thread descendants require an immediate parent_key"
|
|
5301
|
+
});
|
|
5302
|
+
}
|
|
5303
|
+
if (message.scope.thread_id === message.message_id) {
|
|
5304
|
+
context.addIssue({
|
|
5305
|
+
code: external_exports.ZodIssueCode.custom,
|
|
5306
|
+
path: ["scope", "thread_id"],
|
|
5307
|
+
message: "thread descendant thread_id must identify a distinct root message"
|
|
5308
|
+
});
|
|
5309
|
+
}
|
|
5310
|
+
if (message.source_reply_to === void 0) {
|
|
5311
|
+
context.addIssue({
|
|
5312
|
+
code: external_exports.ZodIssueCode.custom,
|
|
5313
|
+
path: ["source_reply_to"],
|
|
5314
|
+
message: "thread descendants require source_reply_to"
|
|
5315
|
+
});
|
|
5316
|
+
}
|
|
5317
|
+
if (message.category !== "chat") {
|
|
5318
|
+
context.addIssue({
|
|
5319
|
+
code: external_exports.ZodIssueCode.custom,
|
|
5320
|
+
path: ["category"],
|
|
5321
|
+
message: "thread descendants must be chat messages"
|
|
5322
|
+
});
|
|
5323
|
+
}
|
|
5324
|
+
}
|
|
5116
5325
|
var CommunicationRecordSchema = RawCommunicationRecordSchema.superRefine((record, context) => {
|
|
5117
5326
|
if (record.record_id !== `${record.room_id}:${record.seq}`) {
|
|
5118
5327
|
context.addIssue({
|
|
@@ -5121,8 +5330,12 @@ var CommunicationRecordSchema = RawCommunicationRecordSchema.superRefine((record
|
|
|
5121
5330
|
message: 'record_id must equal room_id + ":" + seq'
|
|
5122
5331
|
});
|
|
5123
5332
|
}
|
|
5124
|
-
if (record.kind === "message")
|
|
5333
|
+
if (record.kind === "message") {
|
|
5334
|
+
refineMessageCategory(record, context);
|
|
5335
|
+
refineMessageThread(record, context);
|
|
5336
|
+
}
|
|
5125
5337
|
refineRelaySubject(record, context);
|
|
5338
|
+
refineIntakeRejection(record, context);
|
|
5126
5339
|
refineFileRecord(record, context);
|
|
5127
5340
|
});
|
|
5128
5341
|
var AppendRecordSchema = external_exports.discriminatedUnion("kind", [
|
|
@@ -5130,11 +5343,16 @@ var AppendRecordSchema = external_exports.discriminatedUnion("kind", [
|
|
|
5130
5343
|
external_exports.object({ ...AppendCommonShape, ...FileShape }).strict(),
|
|
5131
5344
|
external_exports.object({ ...AppendCommonShape, ...RelayIntentShape }).strict(),
|
|
5132
5345
|
external_exports.object({ ...AppendCommonShape, ...RelayResultShape }).strict(),
|
|
5346
|
+
external_exports.object({ ...AppendCommonShape, ...IntakeRejectionShape }).strict(),
|
|
5133
5347
|
external_exports.object({ ...AppendCommonShape, ...CloseNoticeIntentShape }).strict(),
|
|
5134
5348
|
external_exports.object({ ...AppendCommonShape, ...CloseNoticeResultShape }).strict()
|
|
5135
5349
|
]).superRefine((record, context) => {
|
|
5136
|
-
if (record.kind === "message")
|
|
5350
|
+
if (record.kind === "message") {
|
|
5351
|
+
refineMessageCategory(record, context);
|
|
5352
|
+
refineMessageThread(record, context);
|
|
5353
|
+
}
|
|
5137
5354
|
refineRelaySubject(record, context);
|
|
5355
|
+
refineIntakeRejection(record, context);
|
|
5138
5356
|
refineFileRecord(record, context);
|
|
5139
5357
|
});
|
|
5140
5358
|
|
|
@@ -5431,8 +5649,8 @@ async function roomRequest(command, args) {
|
|
|
5431
5649
|
const role = requiredFlag(parsed, "--role", "room role-command-set");
|
|
5432
5650
|
const value = requiredFlag(parsed, "--commands", "room role-command-set");
|
|
5433
5651
|
const commands = value === "none" ? [] : value.split(",");
|
|
5434
|
-
if (new Set(commands).size !== commands.length || commands.some((item) => !
|
|
5435
|
-
usageError("--commands must be a unique comma-separated list of
|
|
5652
|
+
if (new Set(commands).size !== commands.length || commands.some((item) => !RuntimeCommandGrantPatternSchema.safeParse(item).success)) {
|
|
5653
|
+
usageError("--commands must be a unique comma-separated list of command names, * or namespace.* patterns, or none");
|
|
5436
5654
|
}
|
|
5437
5655
|
return { method: "room.command.role.set", params: { room_id: roomId, role, commands } };
|
|
5438
5656
|
}
|
|
@@ -5443,8 +5661,8 @@ async function roomRequest(command, args) {
|
|
|
5443
5661
|
3,
|
|
5444
5662
|
`room ${command}`
|
|
5445
5663
|
);
|
|
5446
|
-
if (!
|
|
5447
|
-
usageError("runtime command must be a supported
|
|
5664
|
+
if (!RuntimeCommandGrantPatternSchema.safeParse(runtimeCommand).success) {
|
|
5665
|
+
usageError("runtime command must be a supported command name, * or namespace.* pattern");
|
|
5448
5666
|
}
|
|
5449
5667
|
return {
|
|
5450
5668
|
method: command === "command-grant" ? "room.command.grant" : "room.command.revoke",
|