@joe-broadhead/messaging 0.8.0 → 0.9.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/CHANGELOG.md +150 -0
- package/dist/bin/messaging-mcp.js +202 -31
- package/dist/bin/messaging-relay.js +291 -43
- package/dist/bin/messaging.js +290 -32
- package/dist/bin/messagingd.js +1158 -138
- package/dist/lib/modules/core/agent/present.js +5 -0
- package/dist/lib/modules/core/agent-tools.js +12 -0
- package/dist/lib/modules/core/consent.js +54 -14
- package/dist/lib/modules/core/contact-card.js +3 -3
- package/dist/lib/modules/core/index.js +1 -1
- package/dist/lib/modules/core/jelly-host.js +3 -0
- package/dist/lib/modules/core/schema/common.js +2 -0
- package/dist/lib/modules/core/schema/consent.js +20 -3
- package/dist/lib/modules/core/schema/conv-frames.js +10 -3
- package/dist/lib/modules/core/schema/directory-frames.js +8 -3
- package/dist/lib/modules/core/schema/errors.js +3 -2
- package/dist/lib/modules/core/schema/ipc/consent.js +85 -10
- package/dist/lib/modules/core/schema/ipc/conversation-views.js +8 -1
- package/dist/lib/modules/core/schema/ipc/conversations.js +5 -1
- package/dist/lib/modules/core/schema/ipc/device.js +7 -0
- package/dist/lib/modules/core/schema/ipc/jelly.js +14 -7
- package/dist/lib/modules/core/schema/ipc/shapes.js +60 -1
- package/dist/lib/modules/core/schema/ipc.js +51 -3
- package/dist/lib/modules/core/version.js +1 -1
- package/dist/spec/messaging-v1.md +321 -49
- package/dist/types/core/agent/present.d.ts +1 -1
- package/dist/types/core/agent-tools.d.ts +32 -0
- package/dist/types/core/consent.d.ts +30 -7
- package/dist/types/core/contact-card.d.ts +3 -3
- package/dist/types/core/conversation-agent-tools.d.ts +21 -0
- package/dist/types/core/index.d.ts +1 -1
- package/dist/types/core/schema/common.d.ts +2 -0
- package/dist/types/core/schema/consent.d.ts +23 -2
- package/dist/types/core/schema/conv-frames.d.ts +6 -2
- package/dist/types/core/schema/directory-frames.d.ts +8 -3
- package/dist/types/core/schema/envelope.d.ts +2 -0
- package/dist/types/core/schema/errors.d.ts +2 -0
- package/dist/types/core/schema/ipc/consent.d.ts +377 -15
- package/dist/types/core/schema/ipc/conversation-views.d.ts +176 -0
- package/dist/types/core/schema/ipc/conversations.d.ts +368 -0
- package/dist/types/core/schema/ipc/device.d.ts +6 -0
- package/dist/types/core/schema/ipc/jelly.d.ts +14 -6
- package/dist/types/core/schema/ipc/shapes.d.ts +198 -0
- package/dist/types/core/schema/ipc/surfaces.d.ts +1 -0
- package/dist/types/core/schema/ipc/tasks.d.ts +2 -0
- package/dist/types/core/schema/ipc.d.ts +826 -3
- package/dist/types/core/schema/relay.d.ts +4 -0
- package/dist/types/core/version.d.ts +1 -1
- package/dist/types/ipc/server.d.ts +6 -0
- package/package.json +1 -1
|
@@ -6029,6 +6029,7 @@ var init_errors = __esmMin((() => {
|
|
|
6029
6029
|
"jelly_unavailable",
|
|
6030
6030
|
"log_conflict",
|
|
6031
6031
|
"conv_conflict",
|
|
6032
|
+
"conflict",
|
|
6032
6033
|
"stale_epoch",
|
|
6033
6034
|
"device_limit",
|
|
6034
6035
|
"admission_required",
|
|
@@ -7005,6 +7006,12 @@ var init_conversation = __esmMin((() => {
|
|
|
7005
7006
|
function grantProblem(grant) {
|
|
7006
7007
|
const own = "person" in grant.subject && grant.subject.person === grant.person;
|
|
7007
7008
|
if ("conv" in grant.subject && (grant.chat !== void 0 || grant.trustedUntil !== void 0 || grant.discoverable !== void 0)) return "a conversation grant sets only ask and agentMail";
|
|
7009
|
+
if ("relation" in grant.subject) {
|
|
7010
|
+
if (grant.agentMail !== void 0 || grant.trustedUntil !== void 0 || grant.discoverable !== void 0) return "a relation grant sets only chat or ask";
|
|
7011
|
+
if (grant.subject.relation === "outside" && grant.ask !== void 0) return "the outside relation grant sets only chat";
|
|
7012
|
+
if (grant.subject.relation === "outside" && grant.chat === "muted") return "the outside relation grant sets chat open or blocked";
|
|
7013
|
+
if (grant.subject.relation === "org" && grant.chat !== void 0) return "the org relation grant sets only ask";
|
|
7014
|
+
}
|
|
7008
7015
|
if (own && (grant.chat !== void 0 || grant.agentMail !== void 0 || grant.ask !== void 0 || grant.trustedUntil !== void 0)) return "a grant about its own person sets only discoverable";
|
|
7009
7016
|
if (!own && grant.discoverable !== void 0) return "discoverable is set only on a grant about its own person";
|
|
7010
7017
|
if (grant.trustedUntil !== void 0) {
|
|
@@ -7017,7 +7024,7 @@ function cardProblem(card) {
|
|
|
7017
7024
|
if (card.from === card.to) return "a card is about another person";
|
|
7018
7025
|
if (card.can.trustedUntil !== void 0 && card.can.ask !== "open") return "trustedUntil needs ask open";
|
|
7019
7026
|
}
|
|
7020
|
-
var ChatLevel, AgentMailLevel, AskLevel, GrantSubject, GrantSync, CardCan, CardData, CardGetData;
|
|
7027
|
+
var ChatLevel, AgentMailLevel, AskLevel, GrantRelation, GrantSubject, GrantSync, CardCan, CardData, CardGetData;
|
|
7021
7028
|
var init_consent$2 = __esmMin((() => {
|
|
7022
7029
|
init_zod();
|
|
7023
7030
|
init_common();
|
|
@@ -7034,7 +7041,12 @@ var init_consent$2 = __esmMin((() => {
|
|
|
7034
7041
|
"request",
|
|
7035
7042
|
"no"
|
|
7036
7043
|
]);
|
|
7037
|
-
|
|
7044
|
+
GrantRelation = _enum(["outside", "org"]);
|
|
7045
|
+
GrantSubject = union$1([
|
|
7046
|
+
strictObject({ person: PersonId }),
|
|
7047
|
+
strictObject({ conv: ConvId }),
|
|
7048
|
+
strictObject({ relation: GrantRelation })
|
|
7049
|
+
]);
|
|
7038
7050
|
object({
|
|
7039
7051
|
v: literal(PROTOCOL),
|
|
7040
7052
|
realm: RealmId,
|
|
@@ -7483,6 +7495,7 @@ var init_directory_frames = __esmMin((() => {
|
|
|
7483
7495
|
init_common();
|
|
7484
7496
|
init_directory$1();
|
|
7485
7497
|
init_realm$1();
|
|
7498
|
+
init_conversation();
|
|
7486
7499
|
init_jelly$2();
|
|
7487
7500
|
Req$1 = string$1().min(1).max(64);
|
|
7488
7501
|
Size = number$1().int().positive();
|
|
@@ -7580,7 +7593,8 @@ var init_directory_frames = __esmMin((() => {
|
|
|
7580
7593
|
url: WakeUrl,
|
|
7581
7594
|
ticket: Jws.refine((ticket) => ticket.length <= WAKE_TICKET_BYTES, { message: `at most ${WAKE_TICKET_BYTES} bytes` }),
|
|
7582
7595
|
agents: array(SessionName).max(64),
|
|
7583
|
-
awaiting: array(Ulid).max(500)
|
|
7596
|
+
awaiting: array(Ulid).max(500),
|
|
7597
|
+
dms: array(ConvId).max(256).optional()
|
|
7584
7598
|
});
|
|
7585
7599
|
WakeDisarmFrame = object({
|
|
7586
7600
|
t: literal("wake.disarm"),
|
|
@@ -7671,7 +7685,7 @@ var init_directory_frames = __esmMin((() => {
|
|
|
7671
7685
|
]);
|
|
7672
7686
|
}));
|
|
7673
7687
|
// packages/core/dist/schema/ipc/device.js
|
|
7674
|
-
var BindingState, RealmAlarmSummary, DeviceStatus, DeviceChangeView, DeviceListEntry, LinkText, Sas, LinkPreview, KeyFingerprint, LoginUserCode, LoginPurpose, LoginKind, LoginShown, LoginState, DeviceRemoveParams, DeviceApproveParams, IdentityReplaceParams, SignInStep, DirectoryEraseParams, DEVICE_METHODS;
|
|
7688
|
+
var BindingState, RealmAlarmSummary, DeviceStatus, DeviceChangeView, PresenceFeature, DeviceListEntry, LinkText, Sas, LinkPreview, KeyFingerprint, LoginUserCode, LoginPurpose, LoginKind, LoginShown, LoginState, DeviceRemoveParams, DeviceApproveParams, IdentityReplaceParams, SignInStep, DirectoryEraseParams, DEVICE_METHODS;
|
|
7675
7689
|
var init_device = __esmMin((() => {
|
|
7676
7690
|
init_zod();
|
|
7677
7691
|
init_common();
|
|
@@ -7722,6 +7736,7 @@ var init_device = __esmMin((() => {
|
|
|
7722
7736
|
approver: MachineLabel.optional(),
|
|
7723
7737
|
at: Millis
|
|
7724
7738
|
});
|
|
7739
|
+
PresenceFeature = string$1().regex(/^[a-z][a-z0-9-]{0,31}$/, "a feature name");
|
|
7725
7740
|
DeviceListEntry = object({
|
|
7726
7741
|
device: MachineId,
|
|
7727
7742
|
label: MachineLabel,
|
|
@@ -7740,7 +7755,8 @@ var init_device = __esmMin((() => {
|
|
|
7740
7755
|
at: Millis,
|
|
7741
7756
|
reason: UnbindReason,
|
|
7742
7757
|
by: MachineId
|
|
7743
|
-
}).optional()
|
|
7758
|
+
}).optional(),
|
|
7759
|
+
features: array(PresenceFeature).max(32).optional()
|
|
7744
7760
|
});
|
|
7745
7761
|
LinkText = string$1().min(1).max(2048);
|
|
7746
7762
|
Sas = string$1().regex(/^[0-9]{6}$/, "six digits");
|
|
@@ -7947,7 +7963,10 @@ var init_device = __esmMin((() => {
|
|
|
7947
7963
|
};
|
|
7948
7964
|
}));
|
|
7949
7965
|
// packages/core/dist/schema/ipc/shapes.js
|
|
7950
|
-
|
|
7966
|
+
function taskViewRules(schema) {
|
|
7967
|
+
return schema.refine((r) => r.signIn === void 0 || r.task.status.state === "TASK_STATE_AUTH_REQUIRED", "signIn is for an AUTH_REQUIRED task").refine((r) => r.refusal === void 0 || r.task.status.state === "TASK_STATE_REJECTED", "refusal is for a REJECTED task").refine((r) => r.question === void 0 || r.role === "executor" && (r.task.status.state === "TASK_STATE_AUTH_REQUIRED" || r.task.status.state === "TASK_STATE_INPUT_REQUIRED"), "question is for the executor's side of an AUTH_REQUIRED or INPUT_REQUIRED task");
|
|
7968
|
+
}
|
|
7969
|
+
var SessionKey, ActionToken, SendExpect, DirectoryEntry, PeerRef, InboxItem, TaskFollowUp, TASK_SIGN_IN_TOOL_CHARS, TASK_REFUSAL_CHARS, HostLocalId, TaskQuestion, TaskRecordFields, TaskRecord, PersonTask, SendTarget, SendResult;
|
|
7951
7970
|
var init_shapes = __esmMin((() => {
|
|
7952
7971
|
init_zod();
|
|
7953
7972
|
init_a2a();
|
|
@@ -7956,6 +7975,7 @@ var init_shapes = __esmMin((() => {
|
|
|
7956
7975
|
init_delegation$1();
|
|
7957
7976
|
init_errors();
|
|
7958
7977
|
SessionKey = string$1().min(1).max(200);
|
|
7978
|
+
ActionToken = string$1().regex(/^[A-Za-z0-9_-]{43}$/, "action token");
|
|
7959
7979
|
SendExpect = _enum([
|
|
7960
7980
|
"next_turn",
|
|
7961
7981
|
"wake",
|
|
@@ -8026,7 +8046,14 @@ var init_shapes = __esmMin((() => {
|
|
|
8026
8046
|
stage: DeliveryStage,
|
|
8027
8047
|
at: Millis
|
|
8028
8048
|
});
|
|
8029
|
-
|
|
8049
|
+
TASK_SIGN_IN_TOOL_CHARS = LIMITS.previewChars;
|
|
8050
|
+
TASK_REFUSAL_CHARS = LIMITS.requestChars;
|
|
8051
|
+
HostLocalId = string$1().regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,199}$/, "a plain identifier of at most 200 characters");
|
|
8052
|
+
TaskQuestion = strictObject({
|
|
8053
|
+
sessionId: HostLocalId,
|
|
8054
|
+
approvalId: HostLocalId
|
|
8055
|
+
});
|
|
8056
|
+
TaskRecordFields = object({
|
|
8030
8057
|
task: Task$1.extend({ id: Ulid }),
|
|
8031
8058
|
role: _enum(["requester", "executor"]),
|
|
8032
8059
|
key: SessionKey.describe("local session that owns this side of the task"),
|
|
@@ -8034,8 +8061,33 @@ var init_shapes = __esmMin((() => {
|
|
|
8034
8061
|
createdAt: Millis,
|
|
8035
8062
|
updatedAt: Millis,
|
|
8036
8063
|
chain: DelegationSummary.optional(),
|
|
8037
|
-
followUps: array(TaskFollowUp).min(1).max(LIMITS.taskFollowUps).optional()
|
|
8038
|
-
|
|
8064
|
+
followUps: array(TaskFollowUp).min(1).max(LIMITS.taskFollowUps).optional(),
|
|
8065
|
+
agent: SessionName.optional(),
|
|
8066
|
+
person: object({
|
|
8067
|
+
id: PersonId,
|
|
8068
|
+
name: string$1().max(200)
|
|
8069
|
+
}).optional(),
|
|
8070
|
+
org: _enum([
|
|
8071
|
+
"same",
|
|
8072
|
+
"other",
|
|
8073
|
+
"none"
|
|
8074
|
+
]).optional(),
|
|
8075
|
+
signIn: object({
|
|
8076
|
+
tool: string$1().min(1).max(TASK_SIGN_IN_TOOL_CHARS).optional(),
|
|
8077
|
+
by: _enum(["you", "them"])
|
|
8078
|
+
}).optional(),
|
|
8079
|
+
refusal: object({ reason: string$1().min(1).max(TASK_REFUSAL_CHARS) }).optional(),
|
|
8080
|
+
question: TaskQuestion.optional()
|
|
8081
|
+
});
|
|
8082
|
+
TaskRecord = taskViewRules(TaskRecordFields);
|
|
8083
|
+
PersonTask = taskViewRules(TaskRecordFields.omit({ key: true }).extend({
|
|
8084
|
+
key: never().optional(),
|
|
8085
|
+
session: SessionName.describe("this person's agent on this device that holds this side of the task"),
|
|
8086
|
+
cancel: strictObject({
|
|
8087
|
+
name: literal("cancel"),
|
|
8088
|
+
token: ActionToken
|
|
8089
|
+
}).optional()
|
|
8090
|
+
})).refine((r) => r.cancel === void 0 || r.role === "requester", "cancel is for the requester side");
|
|
8039
8091
|
SendTarget = SessionAddress;
|
|
8040
8092
|
SendResult = object({
|
|
8041
8093
|
to: SendTarget,
|
|
@@ -8049,13 +8101,14 @@ var init_shapes = __esmMin((() => {
|
|
|
8049
8101
|
});
|
|
8050
8102
|
}));
|
|
8051
8103
|
// packages/core/dist/schema/ipc/consent.js
|
|
8052
|
-
var GrantTarget, Levels, GrantView, GrantReview, GrantSetParams, AskRequest, ContactRequestView, AgentInvitationRequest, ContactSuggestion, HeldRequest,
|
|
8104
|
+
var GrantTarget, Levels, GrantView, GrantReview, GrantSetParams, RequestAnswer, RequestAction, Actions, AskRequest, ContactRequestView, AgentInvitationRequest, ContactSuggestion, HeldRequest, RequestText, PersonReach, RequestAnswerParams, ContactRequestParams, ReachGroupId, ReachValue, ReachOption, ReachGroup, ReachSnapshot, ReachSetParams, CONSENT_METHODS;
|
|
8053
8105
|
var init_consent$1 = __esmMin((() => {
|
|
8054
8106
|
init_zod();
|
|
8055
8107
|
init_common();
|
|
8056
8108
|
init_conversation();
|
|
8057
8109
|
init_consent$2();
|
|
8058
8110
|
init_directory_frames();
|
|
8111
|
+
init_shapes();
|
|
8059
8112
|
GrantTarget = union$1([strictObject({ person: PersonId }), strictObject({ conv: ConvId })]);
|
|
8060
8113
|
Levels = {
|
|
8061
8114
|
chat: ChatLevel.optional(),
|
|
@@ -8086,6 +8139,18 @@ var init_consent$1 = __esmMin((() => {
|
|
|
8086
8139
|
...Levels,
|
|
8087
8140
|
trust: literal(true).optional()
|
|
8088
8141
|
});
|
|
8142
|
+
RequestAnswer = _enum([
|
|
8143
|
+
"once",
|
|
8144
|
+
"always",
|
|
8145
|
+
"accept",
|
|
8146
|
+
"decline",
|
|
8147
|
+
"block"
|
|
8148
|
+
]);
|
|
8149
|
+
RequestAction = strictObject({
|
|
8150
|
+
name: RequestAnswer,
|
|
8151
|
+
token: ActionToken
|
|
8152
|
+
});
|
|
8153
|
+
Actions = { actions: array(RequestAction).max(4).optional() };
|
|
8089
8154
|
AskRequest = object({
|
|
8090
8155
|
id: Ulid,
|
|
8091
8156
|
kind: _enum(["message", "task"]),
|
|
@@ -8099,7 +8164,8 @@ var init_consent$1 = __esmMin((() => {
|
|
|
8099
8164
|
to: SessionName,
|
|
8100
8165
|
preview: string$1().max(LIMITS.previewChars),
|
|
8101
8166
|
at: Millis,
|
|
8102
|
-
exp: Millis
|
|
8167
|
+
exp: Millis,
|
|
8168
|
+
...Actions
|
|
8103
8169
|
});
|
|
8104
8170
|
ContactRequestView = object({
|
|
8105
8171
|
id: Ulid,
|
|
@@ -8125,7 +8191,8 @@ var init_consent$1 = __esmMin((() => {
|
|
|
8125
8191
|
}),
|
|
8126
8192
|
text: string$1().max(LIMITS.requestChars),
|
|
8127
8193
|
at: Millis,
|
|
8128
|
-
exp: Millis
|
|
8194
|
+
exp: Millis,
|
|
8195
|
+
...Actions
|
|
8129
8196
|
});
|
|
8130
8197
|
AgentInvitationRequest = strictObject({
|
|
8131
8198
|
kind: literal("agent-invitation"),
|
|
@@ -8133,14 +8200,16 @@ var init_consent$1 = __esmMin((() => {
|
|
|
8133
8200
|
cid: ConvId,
|
|
8134
8201
|
from: ParticipantId,
|
|
8135
8202
|
to: ParticipantId,
|
|
8136
|
-
at: Millis
|
|
8203
|
+
at: Millis,
|
|
8204
|
+
...Actions
|
|
8137
8205
|
});
|
|
8138
8206
|
ContactSuggestion = object({
|
|
8139
8207
|
id: Ulid,
|
|
8140
8208
|
kind: literal("suggestion"),
|
|
8141
8209
|
agent: SessionName,
|
|
8142
8210
|
email: Email,
|
|
8143
|
-
at: Millis
|
|
8211
|
+
at: Millis,
|
|
8212
|
+
...Actions
|
|
8144
8213
|
});
|
|
8145
8214
|
HeldRequest = union$1([
|
|
8146
8215
|
AskRequest,
|
|
@@ -8148,13 +8217,6 @@ var init_consent$1 = __esmMin((() => {
|
|
|
8148
8217
|
ContactSuggestion,
|
|
8149
8218
|
AgentInvitationRequest
|
|
8150
8219
|
]);
|
|
8151
|
-
RequestAnswer = _enum([
|
|
8152
|
-
"once",
|
|
8153
|
-
"always",
|
|
8154
|
-
"accept",
|
|
8155
|
-
"decline",
|
|
8156
|
-
"block"
|
|
8157
|
-
]);
|
|
8158
8220
|
RequestText = string$1().min(1).refine((text) => text.length <= LIMITS.requestChars, { message: `at most ${LIMITS.requestChars} UTF-16 code units` });
|
|
8159
8221
|
PersonReach = object({
|
|
8160
8222
|
person: PersonId,
|
|
@@ -8166,14 +8228,57 @@ var init_consent$1 = __esmMin((() => {
|
|
|
8166
8228
|
RequestAnswerParams = strictObject({
|
|
8167
8229
|
id: Ulid,
|
|
8168
8230
|
answer: RequestAnswer,
|
|
8169
|
-
all: boolean().optional()
|
|
8170
|
-
|
|
8231
|
+
all: boolean().optional(),
|
|
8232
|
+
token: ActionToken.optional()
|
|
8233
|
+
}).refine((p) => p.token === void 0 || p.all !== true, "an action token answers one request: drop all");
|
|
8171
8234
|
ContactRequestParams = strictObject({
|
|
8172
8235
|
email: Email,
|
|
8173
8236
|
text: RequestText,
|
|
8174
8237
|
suggestion: Ulid.optional()
|
|
8175
8238
|
});
|
|
8239
|
+
ReachGroupId = _enum(["message", "ask"]);
|
|
8240
|
+
ReachValue = _enum([
|
|
8241
|
+
"open",
|
|
8242
|
+
"ask",
|
|
8243
|
+
"never"
|
|
8244
|
+
]);
|
|
8245
|
+
ReachOption = object({
|
|
8246
|
+
value: ReachValue,
|
|
8247
|
+
label: string$1().max(40),
|
|
8248
|
+
description: string$1().max(300)
|
|
8249
|
+
});
|
|
8250
|
+
ReachGroup = object({
|
|
8251
|
+
id: ReachGroupId,
|
|
8252
|
+
label: string$1().max(80),
|
|
8253
|
+
options: array(ReachOption).length(3),
|
|
8254
|
+
value: ReachValue.nullable(),
|
|
8255
|
+
lapsed: ReachValue.optional()
|
|
8256
|
+
});
|
|
8257
|
+
ReachSnapshot = object({
|
|
8258
|
+
revision: string$1().min(1).max(64),
|
|
8259
|
+
available: boolean(),
|
|
8260
|
+
groups: array(ReachGroup).length(2)
|
|
8261
|
+
});
|
|
8262
|
+
ReachSetParams = strictObject({
|
|
8263
|
+
revision: string$1().min(1).max(64),
|
|
8264
|
+
changes: strictObject({
|
|
8265
|
+
message: ReachValue.optional(),
|
|
8266
|
+
ask: ReachValue.optional()
|
|
8267
|
+
})
|
|
8268
|
+
});
|
|
8176
8269
|
CONSENT_METHODS = {
|
|
8270
|
+
"reach.get": {
|
|
8271
|
+
params: strictObject({}),
|
|
8272
|
+
result: ReachSnapshot
|
|
8273
|
+
},
|
|
8274
|
+
"reach.set": {
|
|
8275
|
+
params: ReachSetParams,
|
|
8276
|
+
result: ReachSnapshot
|
|
8277
|
+
},
|
|
8278
|
+
"reach.set.preview": {
|
|
8279
|
+
params: ReachSetParams,
|
|
8280
|
+
result: object({ sentence: string$1().max(500) })
|
|
8281
|
+
},
|
|
8177
8282
|
"grant.list": {
|
|
8178
8283
|
params: strictObject({ subject: GrantTarget.optional() }),
|
|
8179
8284
|
result: object({
|
|
@@ -8354,6 +8459,7 @@ var init_jelly$1 = __esmMin((() => {
|
|
|
8354
8459
|
}).optional(),
|
|
8355
8460
|
line: string$1().max(120).optional(),
|
|
8356
8461
|
device: NoticeDevice.optional(),
|
|
8462
|
+
key: string$1().regex(/^task:[0-9A-HJKMNP-TV-Z]{26}$/, "task:<task id>").optional(),
|
|
8357
8463
|
at: Millis
|
|
8358
8464
|
});
|
|
8359
8465
|
NoticeCounts = object({ requests: number$1().int().nonnegative() });
|
|
@@ -8424,7 +8530,8 @@ var init_jelly$1 = __esmMin((() => {
|
|
|
8424
8530
|
}),
|
|
8425
8531
|
result: object({
|
|
8426
8532
|
relay: _enum(["armed", "pending"]),
|
|
8427
|
-
awaiting: number$1().int().nonnegative()
|
|
8533
|
+
awaiting: number$1().int().nonnegative(),
|
|
8534
|
+
dms: number$1().int().nonnegative()
|
|
8428
8535
|
})
|
|
8429
8536
|
},
|
|
8430
8537
|
"wake.disarm": {
|
|
@@ -8469,6 +8576,7 @@ var init_conversation_views = __esmMin((() => {
|
|
|
8469
8576
|
init_common();
|
|
8470
8577
|
init_conversation();
|
|
8471
8578
|
init_a2a();
|
|
8579
|
+
init_shapes();
|
|
8472
8580
|
Count$2 = number$1().int().nonnegative().safe();
|
|
8473
8581
|
Seq$1 = number$1().int().nonnegative().safe();
|
|
8474
8582
|
Name = string$1().max(200);
|
|
@@ -8544,7 +8652,11 @@ var init_conversation_views = __esmMin((() => {
|
|
|
8544
8652
|
});
|
|
8545
8653
|
TaskView = object({
|
|
8546
8654
|
id: Ulid,
|
|
8547
|
-
state: TaskState
|
|
8655
|
+
state: TaskState,
|
|
8656
|
+
cancel: strictObject({
|
|
8657
|
+
name: literal("cancel"),
|
|
8658
|
+
token: ActionToken
|
|
8659
|
+
}).optional()
|
|
8548
8660
|
});
|
|
8549
8661
|
EventView = object({
|
|
8550
8662
|
cid: ConvId,
|
|
@@ -8703,6 +8815,11 @@ var init_conversation_views = __esmMin((() => {
|
|
|
8703
8815
|
object({
|
|
8704
8816
|
type: literal("gap"),
|
|
8705
8817
|
pos: Seq$1
|
|
8818
|
+
}),
|
|
8819
|
+
object({
|
|
8820
|
+
type: literal("task"),
|
|
8821
|
+
pos: Seq$1,
|
|
8822
|
+
task: PersonTask
|
|
8706
8823
|
})
|
|
8707
8824
|
]).refine((entry) => entry.type !== "event.update" || entry.cid === entry.event.cid && entry.id === entry.event.id, { message: "event.update names the same conversation and event as its projection" });
|
|
8708
8825
|
}));
|
|
@@ -8818,7 +8935,12 @@ var init_conversations = __esmMin((() => {
|
|
|
8818
8935
|
at: Millis,
|
|
8819
8936
|
cid: ConvId.optional(),
|
|
8820
8937
|
agent: SessionName.optional(),
|
|
8821
|
-
state: _enum([
|
|
8938
|
+
state: _enum([
|
|
8939
|
+
"held",
|
|
8940
|
+
"pending-delivery",
|
|
8941
|
+
"resend",
|
|
8942
|
+
"outdated"
|
|
8943
|
+
])
|
|
8822
8944
|
});
|
|
8823
8945
|
ConvListParams = strictObject({
|
|
8824
8946
|
key: Key,
|
|
@@ -9417,12 +9539,31 @@ var init_ipc = __esmMin((() => {
|
|
|
9417
9539
|
message: strictObject({ parts: array(Part$1).min(1).max(LIMITS.partsPerMessage) }).optional(),
|
|
9418
9540
|
artifact: Artifact.optional(),
|
|
9419
9541
|
append: boolean().optional(),
|
|
9420
|
-
lastChunk: boolean().optional()
|
|
9421
|
-
|
|
9542
|
+
lastChunk: boolean().optional(),
|
|
9543
|
+
signIn: strictObject({ tool: string$1().min(1).max(TASK_SIGN_IN_TOOL_CHARS) }).optional()
|
|
9544
|
+
}).refine((p) => p.signIn === void 0 || p.state === "TASK_STATE_AUTH_REQUIRED", "signIn goes with TASK_STATE_AUTH_REQUIRED"), strictObject({
|
|
9422
9545
|
key: SessionKey,
|
|
9423
9546
|
taskId: Ulid,
|
|
9424
|
-
|
|
9425
|
-
}),
|
|
9547
|
+
question: TaskQuestion.nullable()
|
|
9548
|
+
}), object({ ok: literal(true) }), strictObject({
|
|
9549
|
+
role: _enum(["requester", "executor"]).optional(),
|
|
9550
|
+
state: TaskState.optional(),
|
|
9551
|
+
session: SessionName.optional().describe("only this agent's tasks"),
|
|
9552
|
+
cursor: string$1().min(1).max(200).optional().describe("opaque; from a previous nextCursor"),
|
|
9553
|
+
limit: number$1().int().min(1).max(100).optional()
|
|
9554
|
+
}), object({
|
|
9555
|
+
tasks: array(PersonTask),
|
|
9556
|
+
nextCursor: string$1().max(200).optional().describe("absent when there are no more pages"),
|
|
9557
|
+
total: number$1().int().nonnegative()
|
|
9558
|
+
}), strictObject({
|
|
9559
|
+
taskId: Ulid,
|
|
9560
|
+
role: _enum(["requester", "executor"]).optional()
|
|
9561
|
+
}), strictObject({
|
|
9562
|
+
key: SessionKey.optional(),
|
|
9563
|
+
taskId: Ulid,
|
|
9564
|
+
reason: string$1().max(1e3).optional(),
|
|
9565
|
+
token: ActionToken.optional()
|
|
9566
|
+
}).refine((p) => p.key === void 0 !== (p.token === void 0), "give exactly one of key or token"), strictObject({ keys: array(SessionKey).min(1).max(256) }), strictObject({
|
|
9426
9567
|
name: TeamName,
|
|
9427
9568
|
person: PersonName,
|
|
9428
9569
|
label: MachineLabel,
|
|
@@ -9505,6 +9646,9 @@ var init_ipc = __esmMin((() => {
|
|
|
9505
9646
|
"grant.list",
|
|
9506
9647
|
"grant.set",
|
|
9507
9648
|
"grant.set.preview",
|
|
9649
|
+
"reach.get",
|
|
9650
|
+
"reach.set",
|
|
9651
|
+
"reach.set.preview",
|
|
9508
9652
|
"request.list",
|
|
9509
9653
|
"request.answer",
|
|
9510
9654
|
"request.answer.preview",
|
|
@@ -9514,6 +9658,8 @@ var init_ipc = __esmMin((() => {
|
|
|
9514
9658
|
"notice.subscribe",
|
|
9515
9659
|
"notice.list",
|
|
9516
9660
|
"notice.ack",
|
|
9661
|
+
"tasks.list",
|
|
9662
|
+
"tasks.get",
|
|
9517
9663
|
"device.approve.preview",
|
|
9518
9664
|
"device.remove.preview",
|
|
9519
9665
|
"identity.replace.preview",
|
|
@@ -9668,7 +9814,8 @@ var init_conv_frames = __esmMin((() => {
|
|
|
9668
9814
|
strictObject({
|
|
9669
9815
|
t: literal("conv.capabilities"),
|
|
9670
9816
|
req: Req,
|
|
9671
|
-
outdated: array(PersonId).max(LIMITS.convOpParticipants)
|
|
9817
|
+
outdated: array(PersonId).max(LIMITS.convOpParticipants),
|
|
9818
|
+
unknown: array(PersonId).min(1).max(LIMITS.convOpParticipants).optional()
|
|
9672
9819
|
});
|
|
9673
9820
|
union$1([strictObject({
|
|
9674
9821
|
t: literal("conv.push"),
|
|
@@ -9881,6 +10028,11 @@ var init_agent_tools = __esmMin((() => {
|
|
|
9881
10028
|
titleAuthor: Author$1.optional().describe("With title: who wrote the request; ours when you asked (mine)"),
|
|
9882
10029
|
status: authored("The latest status message").optional(),
|
|
9883
10030
|
statusAuthor: Author$1.optional().describe("With status: who wrote it; ours when you run the task (asked)"),
|
|
10031
|
+
signIn: object({
|
|
10032
|
+
tool: authored("The tool the executor named").optional(),
|
|
10033
|
+
by: _enum(["you", "them"]).describe("Whose sign-in it is: you (your person, for an agent of theirs) or them (the other person); your Messaging daemon decides, never the peer")
|
|
10034
|
+
}).optional().describe("auth_required only: the task waits on a sign-in; the tool was written by the executor, as statusAuthor says"),
|
|
10035
|
+
refusal: object({ reason: authored("The executor's reason") }).optional().describe("rejected only: why the executor declined, in its words, as statusAuthor says"),
|
|
9884
10036
|
createdAt: iso,
|
|
9885
10037
|
updatedAt: iso,
|
|
9886
10038
|
consent: ToolConsentSchema.optional(),
|
|
@@ -10161,7 +10313,7 @@ var init_b64u = __esmMin((() => {
|
|
|
10161
10313
|
// packages/core/dist/version.js
|
|
10162
10314
|
var VERSION;
|
|
10163
10315
|
var init_version = __esmMin((() => {
|
|
10164
|
-
VERSION = "0.
|
|
10316
|
+
VERSION = "0.9.0";
|
|
10165
10317
|
}));
|
|
10166
10318
|
// packages/core/dist/jcs.js
|
|
10167
10319
|
function hasLoneSurrogate(text) {
|
|
@@ -11457,8 +11609,11 @@ var init_jelly_host = __esmMin((() => {
|
|
|
11457
11609
|
"people.search",
|
|
11458
11610
|
"people.get",
|
|
11459
11611
|
"grant.list",
|
|
11612
|
+
"reach.get",
|
|
11460
11613
|
"request.list",
|
|
11461
11614
|
"sessions.list",
|
|
11615
|
+
"tasks.list",
|
|
11616
|
+
"tasks.get",
|
|
11462
11617
|
"notice.subscribe",
|
|
11463
11618
|
"notice.list",
|
|
11464
11619
|
"device.list"
|
|
@@ -13481,6 +13636,7 @@ var init_present = __esmMin((() => {
|
|
|
13481
13636
|
init_errors();
|
|
13482
13637
|
init_peer_text();
|
|
13483
13638
|
init_common();
|
|
13639
|
+
init_ipc();
|
|
13484
13640
|
init_text();
|
|
13485
13641
|
LIMITS.toolTextChars;
|
|
13486
13642
|
createFence({ tag: PEER_FENCE_TAG });
|
|
@@ -14831,7 +14987,8 @@ CREATE TABLE IF NOT EXISTS dir_wakes (
|
|
|
14831
14987
|
);
|
|
14832
14988
|
CREATE INDEX IF NOT EXISTS dir_wakes_exp ON dir_wakes (exp);
|
|
14833
14989
|
`;
|
|
14834
|
-
MIGRATIONS = [
|
|
14990
|
+
MIGRATIONS = [
|
|
14991
|
+
`
|
|
14835
14992
|
CREATE TABLE IF NOT EXISTS conv_logs (
|
|
14836
14993
|
realm TEXT NOT NULL,
|
|
14837
14994
|
cid TEXT NOT NULL,
|
|
@@ -14882,7 +15039,8 @@ CREATE TABLE IF NOT EXISTS conv_shares (
|
|
|
14882
15039
|
CREATE INDEX IF NOT EXISTS conv_shares_to ON conv_shares (realm, cid, to_device, n);
|
|
14883
15040
|
CREATE INDEX IF NOT EXISTS conv_shares_pair ON conv_shares (realm, cid, from_device, to_device);
|
|
14884
15041
|
CREATE INDEX IF NOT EXISTS conv_shares_at ON conv_shares (at);
|
|
14885
|
-
`,
|
|
15042
|
+
`,
|
|
15043
|
+
`
|
|
14886
15044
|
CREATE TABLE IF NOT EXISTS conv_request_decisions (
|
|
14887
15045
|
realm TEXT NOT NULL,
|
|
14888
15046
|
id TEXT NOT NULL,
|
|
@@ -14890,7 +15048,17 @@ CREATE TABLE IF NOT EXISTS conv_request_decisions (
|
|
|
14890
15048
|
decision TEXT NOT NULL,
|
|
14891
15049
|
PRIMARY KEY (realm, id)
|
|
14892
15050
|
);
|
|
14893
|
-
|
|
15051
|
+
`,
|
|
15052
|
+
`
|
|
15053
|
+
CREATE TABLE IF NOT EXISTS dir_wake_dms (
|
|
15054
|
+
device TEXT NOT NULL,
|
|
15055
|
+
cid TEXT NOT NULL,
|
|
15056
|
+
exp INTEGER NOT NULL,
|
|
15057
|
+
PRIMARY KEY (device, cid)
|
|
15058
|
+
);
|
|
15059
|
+
CREATE INDEX IF NOT EXISTS dir_wake_dms_exp ON dir_wake_dms (exp);
|
|
15060
|
+
`
|
|
15061
|
+
];
|
|
14894
15062
|
RELAY_SCHEMA = 1 + MIGRATIONS.length;
|
|
14895
15063
|
RELAY_BASELINE = SCHEMA;
|
|
14896
15064
|
RelayStoreRefusedError = class extends Error {
|
|
@@ -19414,7 +19582,7 @@ var init_pacing = __esmMin((() => {
|
|
|
19414
19582
|
const back = this.#store.pair(to, from)?.last_at ?? null;
|
|
19415
19583
|
return back === null || now - back > 2592e6;
|
|
19416
19584
|
}
|
|
19417
|
-
audience(person, watcher, orgOf, now) {
|
|
19585
|
+
audience(person, watcher, orgOf, now, together) {
|
|
19418
19586
|
if (person === watcher) return true;
|
|
19419
19587
|
const org = orgOf(person);
|
|
19420
19588
|
if (org !== void 0 && org === orgOf(watcher)) return true;
|
|
@@ -19422,7 +19590,8 @@ var init_pacing = __esmMin((() => {
|
|
|
19422
19590
|
const at = this.#store.pair(from, to)?.line_at ?? null;
|
|
19423
19591
|
return at !== null && now - at <= 2592e6;
|
|
19424
19592
|
};
|
|
19425
|
-
|
|
19593
|
+
if (wrote(person, watcher) && wrote(watcher, person)) return true;
|
|
19594
|
+
return together?.(person, watcher) ?? false;
|
|
19426
19595
|
}
|
|
19427
19596
|
#roll(now) {
|
|
19428
19597
|
const day = Math.floor(now / DAY_MS$1);
|
|
@@ -19513,18 +19682,21 @@ var init_wakes = __esmMin((() => {
|
|
|
19513
19682
|
if (claims.aud !== void 0 && claims.aud !== frame.url) throw new MessagingError("invalid_request", "the wake ticket is for another URL");
|
|
19514
19683
|
if (claims.sub !== void 0 && claims.sub !== bound) throw new MessagingError("invalid_request", "the wake ticket is for another host");
|
|
19515
19684
|
this.#clearRetry(device);
|
|
19685
|
+
const dms = [...new Set(frame.dms ?? [])];
|
|
19516
19686
|
this.#store.putWake({
|
|
19517
19687
|
device,
|
|
19518
19688
|
url: frame.url,
|
|
19519
19689
|
ticket: frame.ticket,
|
|
19520
19690
|
agents: [...frame.agents],
|
|
19521
19691
|
awaiting: [...frame.awaiting],
|
|
19692
|
+
dms,
|
|
19522
19693
|
exp: claims.exp * 1e3
|
|
19523
19694
|
});
|
|
19524
19695
|
this.#host.log("wake.armed", {
|
|
19525
19696
|
machine: device,
|
|
19526
19697
|
agents: frame.agents.length,
|
|
19527
|
-
awaiting: frame.awaiting.length
|
|
19698
|
+
awaiting: frame.awaiting.length,
|
|
19699
|
+
dms: dms.length
|
|
19528
19700
|
});
|
|
19529
19701
|
}
|
|
19530
19702
|
forget(device, why) {
|
|
@@ -19565,6 +19737,19 @@ var init_wakes = __esmMin((() => {
|
|
|
19565
19737
|
this.#present(device, "own");
|
|
19566
19738
|
}
|
|
19567
19739
|
}
|
|
19740
|
+
dm(devices, cid) {
|
|
19741
|
+
for (const device of devices) {
|
|
19742
|
+
if (this.#host.online(device)) continue;
|
|
19743
|
+
const row = this.#store.wake(device);
|
|
19744
|
+
if (!row) continue;
|
|
19745
|
+
if (row.exp <= this.#host.now()) {
|
|
19746
|
+
this.forget(device, "removed");
|
|
19747
|
+
continue;
|
|
19748
|
+
}
|
|
19749
|
+
if (!this.#store.wakeDm(device, cid, row.exp)) continue;
|
|
19750
|
+
this.#present(device, "dm");
|
|
19751
|
+
}
|
|
19752
|
+
}
|
|
19568
19753
|
purge(now) {
|
|
19569
19754
|
const gone = this.#store.purgeWakes(now);
|
|
19570
19755
|
if (gone > 0) this.#host.log("wake.expired", { count: gone });
|
|
@@ -20030,7 +20215,7 @@ var init_module$1 = __esmMin((() => {
|
|
|
20030
20215
|
seesPresence(conn, person) {
|
|
20031
20216
|
if (conn.device === void 0 || !this.#watches.get(conn)?.presence.has(person)) return false;
|
|
20032
20217
|
const watcher = this.directory.currentPerson(conn.device);
|
|
20033
|
-
return watcher !== void 0 && this.pacer.audience(person, watcher, (p) => this.directory.orgOf(p), this.#host.now());
|
|
20218
|
+
return watcher !== void 0 && this.pacer.audience(person, watcher, (p) => this.directory.orgOf(p), this.#host.now(), this.#host.together);
|
|
20034
20219
|
}
|
|
20035
20220
|
presenceWatched(conn) {
|
|
20036
20221
|
return this.#watches.get(conn)?.presence ?? new Set();
|
|
@@ -20092,6 +20277,9 @@ var init_store$1 = __esmMin((() => {
|
|
|
20092
20277
|
this.#q(`INSERT INTO dir_wakes (device, url, ticket, agents, awaiting, exp, not_before) VALUES (?, ?, ?, ?, ?, ?, 0)
|
|
20093
20278
|
ON CONFLICT (device) DO UPDATE SET url = excluded.url, ticket = excluded.ticket, agents = excluded.agents,
|
|
20094
20279
|
awaiting = excluded.awaiting, exp = excluded.exp, not_before = 0`).run(row.device, row.url, row.ticket, JSON.stringify(row.agents), JSON.stringify(row.awaiting), row.exp);
|
|
20280
|
+
this.#q("DELETE FROM dir_wake_dms WHERE device = ?").run(row.device);
|
|
20281
|
+
const put = this.#q("INSERT OR IGNORE INTO dir_wake_dms (device, cid, exp) VALUES (?, ?, ?)");
|
|
20282
|
+
for (const cid of row.dms) put.run(row.device, cid, row.exp);
|
|
20095
20283
|
});
|
|
20096
20284
|
}
|
|
20097
20285
|
wake(device) {
|
|
@@ -20115,6 +20303,13 @@ var init_store$1 = __esmMin((() => {
|
|
|
20115
20303
|
notBefore: Number(row.not_before)
|
|
20116
20304
|
};
|
|
20117
20305
|
}
|
|
20306
|
+
wakeDm(device, cid, exp) {
|
|
20307
|
+
return this.#q("SELECT 1 FROM dir_wake_dms WHERE device = ? AND cid = ? AND exp = ?").get(device, cid, exp) !== void 0;
|
|
20308
|
+
}
|
|
20309
|
+
wakeDmCount(device) {
|
|
20310
|
+
const row = this.#q("SELECT COUNT(*) AS n FROM dir_wake_dms WHERE device = ?").get(device);
|
|
20311
|
+
return Number(row.n);
|
|
20312
|
+
}
|
|
20118
20313
|
setWakeNotBefore(device, at) {
|
|
20119
20314
|
this.transaction(() => {
|
|
20120
20315
|
this.#q("UPDATE dir_wakes SET not_before = ? WHERE device = ?").run(at, device);
|
|
@@ -20122,11 +20317,13 @@ var init_store$1 = __esmMin((() => {
|
|
|
20122
20317
|
}
|
|
20123
20318
|
deleteWake(device) {
|
|
20124
20319
|
return this.transaction(() => {
|
|
20320
|
+
this.#q("DELETE FROM dir_wake_dms WHERE device = ?").run(device);
|
|
20125
20321
|
return Number(this.#q("DELETE FROM dir_wakes WHERE device = ?").run(device).changes) > 0;
|
|
20126
20322
|
});
|
|
20127
20323
|
}
|
|
20128
20324
|
purgeWakes(now) {
|
|
20129
20325
|
return this.transaction(() => {
|
|
20326
|
+
this.#q("DELETE FROM dir_wake_dms WHERE exp <= ?").run(now);
|
|
20130
20327
|
return Number(this.#q("DELETE FROM dir_wakes WHERE exp <= ?").run(now).changes);
|
|
20131
20328
|
});
|
|
20132
20329
|
}
|
|
@@ -20264,7 +20461,7 @@ var init_store$1 = __esmMin((() => {
|
|
|
20264
20461
|
};
|
|
20265
20462
|
}));
|
|
20266
20463
|
// packages/relay/dist/conv/module.js
|
|
20267
|
-
var CONV_FRAME_TYPES, persons, readers, digestOf, REPLY_BUDGET, ConvModule;
|
|
20464
|
+
var CONV_FRAME_TYPES, persons, readers, TOGETHER_SCAN, digestOf, REPLY_BUDGET, ConvModule;
|
|
20268
20465
|
var init_module = __esmMin((() => {
|
|
20269
20466
|
init_dist();
|
|
20270
20467
|
init_module$1();
|
|
@@ -20281,6 +20478,7 @@ var init_module = __esmMin((() => {
|
|
|
20281
20478
|
]);
|
|
20282
20479
|
persons = (state) => new Set(state?.participants.map((p) => p.person) ?? []);
|
|
20283
20480
|
readers = (state) => new Set(state?.participants.filter((p) => p.state === "member").map((p) => p.person) ?? []);
|
|
20481
|
+
TOGETHER_SCAN = 50;
|
|
20284
20482
|
digestOf = (raw) => b64u.encode(convEventDigest(raw));
|
|
20285
20483
|
REPLY_BUDGET = Math.floor(LIMITS.frameBytes * 3 / 4);
|
|
20286
20484
|
ConvModule = class {
|
|
@@ -20293,6 +20491,8 @@ var init_module = __esmMin((() => {
|
|
|
20293
20491
|
#rekeys = new RateLimiter(LIMITS.convRekeysPerHour, LIMITS.convRekeysPerHour / 60);
|
|
20294
20492
|
#creates = new RateLimiter(LIMITS.convCreatesPerHour, LIMITS.convCreatesPerHour / 60);
|
|
20295
20493
|
#shares = new RateLimiter(LIMITS.convSharesPerMinute);
|
|
20494
|
+
#capsAsked = new Map();
|
|
20495
|
+
#capsDay = -1;
|
|
20296
20496
|
constructor(store, host, options = {}) {
|
|
20297
20497
|
this.#store = store;
|
|
20298
20498
|
this.#host = host;
|
|
@@ -20423,6 +20623,10 @@ var init_module = __esmMin((() => {
|
|
|
20423
20623
|
if (event.class === "op") this.#push(realm, new Set([...after].filter((p) => !before.has(p) && !readers(state).has(p))), machine, push);
|
|
20424
20624
|
const author = this.#host.realm(realm)?.device(machine)?.person;
|
|
20425
20625
|
if (event.class === "msg" && event.wake !== void 0 && author !== void 0) this.#host.woken?.(realm, author, event.wake);
|
|
20626
|
+
if (event.class === "msg" && state.kind === "dm" && author !== void 0) {
|
|
20627
|
+
const others = [...readers(state)].filter((p) => p !== author);
|
|
20628
|
+
if (others.length > 0) this.#host.dmEvent?.(realm, author, cid, others);
|
|
20629
|
+
}
|
|
20426
20630
|
},
|
|
20427
20631
|
failed: (error) => this.#host.nack(conn, req, error)
|
|
20428
20632
|
}, () => this.#logs.delete(key));
|
|
@@ -20600,16 +20804,46 @@ var init_module = __esmMin((() => {
|
|
|
20600
20804
|
const parsed = ConvCapsFrame.safeParse(raw);
|
|
20601
20805
|
if (!parsed.success) throw new MessagingError("invalid_request", "malformed conv.caps");
|
|
20602
20806
|
const { req, persons } = parsed.data;
|
|
20603
|
-
const
|
|
20807
|
+
const realm = conn.auth.team;
|
|
20808
|
+
const asker = this.#host.realm(realm)?.device(conn.auth.machine)?.person;
|
|
20809
|
+
if (asker === void 0) throw new MessagingError("forbidden", "conv.caps needs a current device");
|
|
20810
|
+
const day = Math.floor(this.#host.now() / 864e5);
|
|
20811
|
+
if (this.#capsDay !== day) {
|
|
20812
|
+
this.#capsDay = day;
|
|
20813
|
+
this.#capsAsked.clear();
|
|
20814
|
+
}
|
|
20815
|
+
const named = [...new Set(persons)];
|
|
20816
|
+
const asked = this.#capsAsked.get(`${realm} ${asker}`) ?? new Set();
|
|
20817
|
+
const unknown = [];
|
|
20818
|
+
for (const p of named) {
|
|
20819
|
+
if (p === asker || asked.has(p) || (this.#host.related?.(realm, asker, p) ?? true)) continue;
|
|
20820
|
+
if (asked.size < LIMITS.requestsPerDay) asked.add(p);
|
|
20821
|
+
else unknown.push(p);
|
|
20822
|
+
}
|
|
20823
|
+
this.#capsAsked.set(`${realm} ${asker}`, asked);
|
|
20824
|
+
const outdated = named.filter((p) => !unknown.includes(p)).filter((person) => {
|
|
20604
20825
|
const devices = this.#host.features?.(conn.auth.team, person) ?? [];
|
|
20605
20826
|
return devices.length > 0 && devices.every((features) => !features.includes("conversations"));
|
|
20606
20827
|
});
|
|
20607
20828
|
this.#host.send(conn, JSON.stringify({
|
|
20608
20829
|
t: "conv.capabilities",
|
|
20609
20830
|
req,
|
|
20610
|
-
outdated
|
|
20831
|
+
outdated,
|
|
20832
|
+
...unknown.length ? { unknown } : {}
|
|
20611
20833
|
}), "conv.capabilities");
|
|
20612
20834
|
}
|
|
20835
|
+
together(realm, a, b) {
|
|
20836
|
+
if (a === b) return true;
|
|
20837
|
+
for (const cid of this.#store.sharedCids(realm, a, b, TOGETHER_SCAN)) {
|
|
20838
|
+
const log = this.#load(realm, cid);
|
|
20839
|
+
const members = readers(log?.state());
|
|
20840
|
+
if (!log || !members.has(a) || !members.has(b)) continue;
|
|
20841
|
+
try {
|
|
20842
|
+
if (requestLogState(log, this.#binding(realm)).active) return true;
|
|
20843
|
+
} catch {}
|
|
20844
|
+
}
|
|
20845
|
+
return false;
|
|
20846
|
+
}
|
|
20613
20847
|
#head(conn, raw) {
|
|
20614
20848
|
const parsed = ConvHeadFrame.safeParse(raw);
|
|
20615
20849
|
if (!parsed.success) throw new MessagingError("invalid_request", "invalid conv.head frame");
|
|
@@ -20731,6 +20965,7 @@ var init_store = __esmMin((() => {
|
|
|
20731
20965
|
isMember: prepare("SELECT 1 AS x FROM conv_members WHERE realm = ? AND person = ? AND cid = ?"),
|
|
20732
20966
|
convsOf: prepare("SELECT COUNT(*) AS n FROM conv_members WHERE realm = ? AND person = ?"),
|
|
20733
20967
|
cidsOf: prepare("SELECT cid FROM conv_members WHERE realm = ? AND person = ? AND cid > ? ORDER BY cid LIMIT ?"),
|
|
20968
|
+
sharedCids: prepare("SELECT a.cid AS cid FROM conv_members a JOIN conv_members b ON b.realm = a.realm AND b.cid = a.cid WHERE a.realm = ? AND a.person = ? AND b.person = ? ORDER BY a.cid LIMIT ?"),
|
|
20734
20969
|
shareById: prepare("SELECT digest FROM conv_shares WHERE realm = ? AND cid = ? AND id = ?"),
|
|
20735
20970
|
pairCount: prepare("SELECT COUNT(*) AS n FROM conv_shares WHERE realm = ? AND cid = ? AND from_device = ? AND to_device = ?"),
|
|
20736
20971
|
insertShare: prepare("INSERT INTO conv_shares (realm, cid, id, from_device, to_device, digest, at, event) VALUES (?, ?, ?, ?, ?, ?, ?, ?) RETURNING n"),
|
|
@@ -20769,6 +21004,9 @@ var init_store = __esmMin((() => {
|
|
|
20769
21004
|
cidsOf(realm, person, after, limit) {
|
|
20770
21005
|
return this.#sql.cidsOf.all(realm, person, after, limit).map((r) => r.cid);
|
|
20771
21006
|
}
|
|
21007
|
+
sharedCids(realm, a, b, limit) {
|
|
21008
|
+
return this.#sql.sharedCids.all(realm, a, b, limit).map((r) => r.cid);
|
|
21009
|
+
}
|
|
20772
21010
|
shareDigest(realm, cid, id) {
|
|
20773
21011
|
return this.#sql.shareById.get(realm, cid, id)?.digest;
|
|
20774
21012
|
}
|
|
@@ -21076,7 +21314,8 @@ var init_server = __esmMin((() => {
|
|
|
21076
21314
|
connections: () => online()?.values() ?? [],
|
|
21077
21315
|
purge: (device) => this.#store.dropMachine(realm, device),
|
|
21078
21316
|
remove: (device, frame) => this.#removeDevice(realm, device, frame),
|
|
21079
|
-
replayPresence: (conn, persons) => this.#replayPresence(conn, persons)
|
|
21317
|
+
replayPresence: (conn, persons) => this.#replayPresence(conn, persons),
|
|
21318
|
+
together: (a, b) => this.#conv.together(realm, a, b)
|
|
21080
21319
|
});
|
|
21081
21320
|
realm = module.directory.realm;
|
|
21082
21321
|
this.#log.event("directory.serving", {
|
|
@@ -21101,6 +21340,11 @@ var init_server = __esmMin((() => {
|
|
|
21101
21340
|
wasRemovedDevice: (realm, device) => this.#dir ? realm === this.#dir.directory.realm && this.#dir.directory.wasRemoved(device) : this.#rosters.get(realm)?.wasRemoved(device) ?? false,
|
|
21102
21341
|
wasDevice: (realm, person, device) => this.#dir ? realm === this.#dir.directory.realm && this.#dir.directory.personOfDevice(device) === person : this.#rosters.get(realm)?.member(device)?.person === person,
|
|
21103
21342
|
online: (realm) => this.#online.get(realm) ?? new Map(),
|
|
21343
|
+
related: (realm, asker, person) => {
|
|
21344
|
+
const dir = this.#dir;
|
|
21345
|
+
if (!dir || realm !== dir.directory.realm) return true;
|
|
21346
|
+
return dir.pacer.audience(person, asker, (p) => dir.directory.orgOf(p), this.#now(), (a, b) => this.#conv.together(realm, a, b));
|
|
21347
|
+
},
|
|
21104
21348
|
features: (realm, person) => {
|
|
21105
21349
|
const devices = this.#dir ? realm === this.#dir.directory.realm ? this.#dir.directory.devicesOf(person) : [] : this.#rosters.get(realm)?.members().filter((m) => m.person === person).map((m) => m.machine) ?? [];
|
|
21106
21350
|
const found = [];
|
|
@@ -21115,6 +21359,10 @@ var init_server = __esmMin((() => {
|
|
|
21115
21359
|
woken: (realm, person, sessions) => {
|
|
21116
21360
|
const dir = this.#dir;
|
|
21117
21361
|
if (dir && realm === dir.directory.realm) this.#guard("wake.hinted", () => dir.wakes.hinted(dir.directory.devicesOf(person), sessions));
|
|
21362
|
+
},
|
|
21363
|
+
dmEvent: (realm, _person, cid, others) => {
|
|
21364
|
+
const dir = this.#dir;
|
|
21365
|
+
if (dir && realm === dir.directory.realm) this.#guard("wake.dm", () => dir.wakes.dm(others.flatMap((p) => dir.directory.devicesOf(p)), cid));
|
|
21118
21366
|
}
|
|
21119
21367
|
});
|
|
21120
21368
|
}
|