@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
package/dist/bin/messagingd.js
CHANGED
|
@@ -5868,7 +5868,8 @@ var init_common = __esmMin((() => {
|
|
|
5868
5868
|
URI = {
|
|
5869
5869
|
binding: "urn:messaging:binding:relay:v1",
|
|
5870
5870
|
provenance: "urn:messaging:ext:provenance:v1",
|
|
5871
|
-
presence: "urn:messaging:ext:presence:v1"
|
|
5871
|
+
presence: "urn:messaging:ext:presence:v1",
|
|
5872
|
+
signIn: "urn:messaging:ext:sign-in:v1"
|
|
5872
5873
|
};
|
|
5873
5874
|
Base64Url = string$1().regex(/^[A-Za-z0-9_-]*$/, "base64url without padding");
|
|
5874
5875
|
Key32 = string$1().regex(/^[A-Za-z0-9_-]{43}$/, "32 bytes, base64url without padding");
|
|
@@ -6039,6 +6040,7 @@ var init_errors = __esmMin((() => {
|
|
|
6039
6040
|
"jelly_unavailable",
|
|
6040
6041
|
"log_conflict",
|
|
6041
6042
|
"conv_conflict",
|
|
6043
|
+
"conflict",
|
|
6042
6044
|
"stale_epoch",
|
|
6043
6045
|
"device_limit",
|
|
6044
6046
|
"admission_required",
|
|
@@ -6345,7 +6347,7 @@ var init_directory$2 = __esmMin((() => {
|
|
|
6345
6347
|
});
|
|
6346
6348
|
}));
|
|
6347
6349
|
// packages/core/dist/schema/a2a.js
|
|
6348
|
-
var Struct, TaskState, TERMINAL_STATES, Role, Part$1, Message, TaskStatus, Artifact, Task$1, TaskStatusUpdateEvent, TaskArtifactUpdateEvent;
|
|
6350
|
+
var Struct, TaskState, TERMINAL_STATES, INTERRUPTED_STATES, Role, Part$1, Message, TaskStatus, Artifact, Task$1, TaskStatusUpdateEvent, TaskArtifactUpdateEvent;
|
|
6349
6351
|
var init_a2a = __esmMin((() => {
|
|
6350
6352
|
init_zod();
|
|
6351
6353
|
Struct = record(string$1(), unknown());
|
|
@@ -6365,6 +6367,7 @@ var init_a2a = __esmMin((() => {
|
|
|
6365
6367
|
"TASK_STATE_CANCELED",
|
|
6366
6368
|
"TASK_STATE_REJECTED"
|
|
6367
6369
|
];
|
|
6370
|
+
INTERRUPTED_STATES = ["TASK_STATE_INPUT_REQUIRED", "TASK_STATE_AUTH_REQUIRED"];
|
|
6368
6371
|
Role = _enum(["ROLE_USER", "ROLE_AGENT"]);
|
|
6369
6372
|
Part$1 = object$1({
|
|
6370
6373
|
text: string$1().optional(),
|
|
@@ -7029,6 +7032,12 @@ var init_conversation = __esmMin((() => {
|
|
|
7029
7032
|
function grantProblem(grant) {
|
|
7030
7033
|
const own = "person" in grant.subject && grant.subject.person === grant.person;
|
|
7031
7034
|
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";
|
|
7035
|
+
if ("relation" in grant.subject) {
|
|
7036
|
+
if (grant.agentMail !== void 0 || grant.trustedUntil !== void 0 || grant.discoverable !== void 0) return "a relation grant sets only chat or ask";
|
|
7037
|
+
if (grant.subject.relation === "outside" && grant.ask !== void 0) return "the outside relation grant sets only chat";
|
|
7038
|
+
if (grant.subject.relation === "outside" && grant.chat === "muted") return "the outside relation grant sets chat open or blocked";
|
|
7039
|
+
if (grant.subject.relation === "org" && grant.chat !== void 0) return "the org relation grant sets only ask";
|
|
7040
|
+
}
|
|
7032
7041
|
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";
|
|
7033
7042
|
if (!own && grant.discoverable !== void 0) return "discoverable is set only on a grant about its own person";
|
|
7034
7043
|
if (grant.trustedUntil !== void 0) {
|
|
@@ -7041,7 +7050,7 @@ function cardProblem(card) {
|
|
|
7041
7050
|
if (card.from === card.to) return "a card is about another person";
|
|
7042
7051
|
if (card.can.trustedUntil !== void 0 && card.can.ask !== "open") return "trustedUntil needs ask open";
|
|
7043
7052
|
}
|
|
7044
|
-
var ChatLevel, AgentMailLevel, AskLevel, GrantSubject, ConsentGrant, GrantSync, CardCan, ContactCard, CardData, CardGetData;
|
|
7053
|
+
var ChatLevel, AgentMailLevel, AskLevel, GrantRelation, GrantSubject, ConsentGrant, GrantSync, CardCan, ContactCard, CardData, CardGetData;
|
|
7045
7054
|
var init_consent$2 = __esmMin((() => {
|
|
7046
7055
|
init_zod();
|
|
7047
7056
|
init_common();
|
|
@@ -7058,7 +7067,12 @@ var init_consent$2 = __esmMin((() => {
|
|
|
7058
7067
|
"request",
|
|
7059
7068
|
"no"
|
|
7060
7069
|
]);
|
|
7061
|
-
|
|
7070
|
+
GrantRelation = _enum(["outside", "org"]);
|
|
7071
|
+
GrantSubject = union$1([
|
|
7072
|
+
strictObject({ person: PersonId }),
|
|
7073
|
+
strictObject({ conv: ConvId }),
|
|
7074
|
+
strictObject({ relation: GrantRelation })
|
|
7075
|
+
]);
|
|
7062
7076
|
ConsentGrant = object$1({
|
|
7063
7077
|
v: literal(PROTOCOL),
|
|
7064
7078
|
realm: RealmId,
|
|
@@ -7520,6 +7534,7 @@ var init_directory_frames = __esmMin((() => {
|
|
|
7520
7534
|
init_common();
|
|
7521
7535
|
init_directory$2();
|
|
7522
7536
|
init_realm$1();
|
|
7537
|
+
init_conversation();
|
|
7523
7538
|
init_jelly$3();
|
|
7524
7539
|
Req$1 = string$1().min(1).max(64);
|
|
7525
7540
|
Size = number$1().int().positive();
|
|
@@ -7617,7 +7632,8 @@ var init_directory_frames = __esmMin((() => {
|
|
|
7617
7632
|
url: WakeUrl,
|
|
7618
7633
|
ticket: Jws.refine((ticket) => ticket.length <= WAKE_TICKET_BYTES, { message: `at most ${WAKE_TICKET_BYTES} bytes` }),
|
|
7619
7634
|
agents: array(SessionName).max(64),
|
|
7620
|
-
awaiting: array(Ulid).max(500)
|
|
7635
|
+
awaiting: array(Ulid).max(500),
|
|
7636
|
+
dms: array(ConvId).max(256).optional()
|
|
7621
7637
|
});
|
|
7622
7638
|
WakeDisarmFrame = object$1({
|
|
7623
7639
|
t: literal("wake.disarm"),
|
|
@@ -7708,7 +7724,7 @@ var init_directory_frames = __esmMin((() => {
|
|
|
7708
7724
|
]);
|
|
7709
7725
|
}));
|
|
7710
7726
|
// packages/core/dist/schema/ipc/device.js
|
|
7711
|
-
var BindingState, RealmAlarmSummary, DeviceStatus, DeviceChangeView, DeviceListEntry, LinkText, Sas, LinkPreview, KeyFingerprint, LoginUserCode, LoginPurpose, LoginKind, LoginShown, LoginState, DeviceRemoveParams, DeviceApproveParams, IdentityReplaceParams, SignInStep, DirectoryEraseParams, DEVICE_METHODS;
|
|
7727
|
+
var BindingState, RealmAlarmSummary, DeviceStatus, DeviceChangeView, PresenceFeature, DeviceListEntry, LinkText, Sas, LinkPreview, KeyFingerprint, LoginUserCode, LoginPurpose, LoginKind, LoginShown, LoginState, DeviceRemoveParams, DeviceApproveParams, IdentityReplaceParams, SignInStep, DirectoryEraseParams, DEVICE_METHODS;
|
|
7712
7728
|
var init_device = __esmMin((() => {
|
|
7713
7729
|
init_zod();
|
|
7714
7730
|
init_common();
|
|
@@ -7759,6 +7775,7 @@ var init_device = __esmMin((() => {
|
|
|
7759
7775
|
approver: MachineLabel.optional(),
|
|
7760
7776
|
at: Millis
|
|
7761
7777
|
});
|
|
7778
|
+
PresenceFeature = string$1().regex(/^[a-z][a-z0-9-]{0,31}$/, "a feature name");
|
|
7762
7779
|
DeviceListEntry = object$1({
|
|
7763
7780
|
device: MachineId,
|
|
7764
7781
|
label: MachineLabel,
|
|
@@ -7777,7 +7794,8 @@ var init_device = __esmMin((() => {
|
|
|
7777
7794
|
at: Millis,
|
|
7778
7795
|
reason: UnbindReason,
|
|
7779
7796
|
by: MachineId
|
|
7780
|
-
}).optional()
|
|
7797
|
+
}).optional(),
|
|
7798
|
+
features: array(PresenceFeature).max(32).optional()
|
|
7781
7799
|
});
|
|
7782
7800
|
LinkText = string$1().min(1).max(2048);
|
|
7783
7801
|
Sas = string$1().regex(/^[0-9]{6}$/, "six digits");
|
|
@@ -7984,7 +8002,10 @@ var init_device = __esmMin((() => {
|
|
|
7984
8002
|
};
|
|
7985
8003
|
}));
|
|
7986
8004
|
// packages/core/dist/schema/ipc/shapes.js
|
|
7987
|
-
|
|
8005
|
+
function taskViewRules(schema) {
|
|
8006
|
+
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");
|
|
8007
|
+
}
|
|
8008
|
+
var SessionKey, ActionToken, SendExpect, DirectoryEntry, PeerRef, InboxItem, TaskFollowUp, TASK_SIGN_IN_TOOL_CHARS, TASK_REFUSAL_CHARS, HostLocalId, TaskQuestion, TaskRecordFields, TaskRecord, PersonTask, SendTarget, SendResult;
|
|
7988
8009
|
var init_shapes = __esmMin((() => {
|
|
7989
8010
|
init_zod();
|
|
7990
8011
|
init_a2a();
|
|
@@ -7993,6 +8014,7 @@ var init_shapes = __esmMin((() => {
|
|
|
7993
8014
|
init_delegation$2();
|
|
7994
8015
|
init_errors();
|
|
7995
8016
|
SessionKey = string$1().min(1).max(200);
|
|
8017
|
+
ActionToken = string$1().regex(/^[A-Za-z0-9_-]{43}$/, "action token");
|
|
7996
8018
|
SendExpect = _enum([
|
|
7997
8019
|
"next_turn",
|
|
7998
8020
|
"wake",
|
|
@@ -8063,7 +8085,14 @@ var init_shapes = __esmMin((() => {
|
|
|
8063
8085
|
stage: DeliveryStage,
|
|
8064
8086
|
at: Millis
|
|
8065
8087
|
});
|
|
8066
|
-
|
|
8088
|
+
TASK_SIGN_IN_TOOL_CHARS = LIMITS.previewChars;
|
|
8089
|
+
TASK_REFUSAL_CHARS = LIMITS.requestChars;
|
|
8090
|
+
HostLocalId = string$1().regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,199}$/, "a plain identifier of at most 200 characters");
|
|
8091
|
+
TaskQuestion = strictObject({
|
|
8092
|
+
sessionId: HostLocalId,
|
|
8093
|
+
approvalId: HostLocalId
|
|
8094
|
+
});
|
|
8095
|
+
TaskRecordFields = object$1({
|
|
8067
8096
|
task: Task$1.extend({ id: Ulid }),
|
|
8068
8097
|
role: _enum(["requester", "executor"]),
|
|
8069
8098
|
key: SessionKey.describe("local session that owns this side of the task"),
|
|
@@ -8071,8 +8100,33 @@ var init_shapes = __esmMin((() => {
|
|
|
8071
8100
|
createdAt: Millis,
|
|
8072
8101
|
updatedAt: Millis,
|
|
8073
8102
|
chain: DelegationSummary.optional(),
|
|
8074
|
-
followUps: array(TaskFollowUp).min(1).max(LIMITS.taskFollowUps).optional()
|
|
8075
|
-
|
|
8103
|
+
followUps: array(TaskFollowUp).min(1).max(LIMITS.taskFollowUps).optional(),
|
|
8104
|
+
agent: SessionName.optional(),
|
|
8105
|
+
person: object$1({
|
|
8106
|
+
id: PersonId,
|
|
8107
|
+
name: string$1().max(200)
|
|
8108
|
+
}).optional(),
|
|
8109
|
+
org: _enum([
|
|
8110
|
+
"same",
|
|
8111
|
+
"other",
|
|
8112
|
+
"none"
|
|
8113
|
+
]).optional(),
|
|
8114
|
+
signIn: object$1({
|
|
8115
|
+
tool: string$1().min(1).max(TASK_SIGN_IN_TOOL_CHARS).optional(),
|
|
8116
|
+
by: _enum(["you", "them"])
|
|
8117
|
+
}).optional(),
|
|
8118
|
+
refusal: object$1({ reason: string$1().min(1).max(TASK_REFUSAL_CHARS) }).optional(),
|
|
8119
|
+
question: TaskQuestion.optional()
|
|
8120
|
+
});
|
|
8121
|
+
TaskRecord = taskViewRules(TaskRecordFields);
|
|
8122
|
+
PersonTask = taskViewRules(TaskRecordFields.omit({ key: true }).extend({
|
|
8123
|
+
key: never().optional(),
|
|
8124
|
+
session: SessionName.describe("this person's agent on this device that holds this side of the task"),
|
|
8125
|
+
cancel: strictObject({
|
|
8126
|
+
name: literal("cancel"),
|
|
8127
|
+
token: ActionToken
|
|
8128
|
+
}).optional()
|
|
8129
|
+
})).refine((r) => r.cancel === void 0 || r.role === "requester", "cancel is for the requester side");
|
|
8076
8130
|
SendTarget = SessionAddress;
|
|
8077
8131
|
SendResult = object$1({
|
|
8078
8132
|
to: SendTarget,
|
|
@@ -8086,13 +8140,14 @@ var init_shapes = __esmMin((() => {
|
|
|
8086
8140
|
});
|
|
8087
8141
|
}));
|
|
8088
8142
|
// packages/core/dist/schema/ipc/consent.js
|
|
8089
|
-
var GrantTarget, Levels, GrantView, GrantReview, GrantSetParams, AskRequest, ContactRequestView, AgentInvitationRequest, ContactSuggestion, HeldRequest,
|
|
8143
|
+
var GrantTarget, Levels, GrantView, GrantReview, GrantSetParams, RequestAnswer, RequestAction, Actions, AskRequest, ContactRequestView, AgentInvitationRequest, ContactSuggestion, HeldRequest, RequestText, PersonReach, RequestAnswerParams, ContactRequestParams, ReachGroupId, ReachValue, ReachOption, ReachGroup, ReachSnapshot, ReachSetParams, REACH_QUESTIONS, CONSENT_METHODS;
|
|
8090
8144
|
var init_consent$1 = __esmMin((() => {
|
|
8091
8145
|
init_zod();
|
|
8092
8146
|
init_common();
|
|
8093
8147
|
init_conversation();
|
|
8094
8148
|
init_consent$2();
|
|
8095
8149
|
init_directory_frames();
|
|
8150
|
+
init_shapes();
|
|
8096
8151
|
GrantTarget = union$1([strictObject({ person: PersonId }), strictObject({ conv: ConvId })]);
|
|
8097
8152
|
Levels = {
|
|
8098
8153
|
chat: ChatLevel.optional(),
|
|
@@ -8123,6 +8178,18 @@ var init_consent$1 = __esmMin((() => {
|
|
|
8123
8178
|
...Levels,
|
|
8124
8179
|
trust: literal(true).optional()
|
|
8125
8180
|
});
|
|
8181
|
+
RequestAnswer = _enum([
|
|
8182
|
+
"once",
|
|
8183
|
+
"always",
|
|
8184
|
+
"accept",
|
|
8185
|
+
"decline",
|
|
8186
|
+
"block"
|
|
8187
|
+
]);
|
|
8188
|
+
RequestAction = strictObject({
|
|
8189
|
+
name: RequestAnswer,
|
|
8190
|
+
token: ActionToken
|
|
8191
|
+
});
|
|
8192
|
+
Actions = { actions: array(RequestAction).max(4).optional() };
|
|
8126
8193
|
AskRequest = object$1({
|
|
8127
8194
|
id: Ulid,
|
|
8128
8195
|
kind: _enum(["message", "task"]),
|
|
@@ -8136,7 +8203,8 @@ var init_consent$1 = __esmMin((() => {
|
|
|
8136
8203
|
to: SessionName,
|
|
8137
8204
|
preview: string$1().max(LIMITS.previewChars),
|
|
8138
8205
|
at: Millis,
|
|
8139
|
-
exp: Millis
|
|
8206
|
+
exp: Millis,
|
|
8207
|
+
...Actions
|
|
8140
8208
|
});
|
|
8141
8209
|
ContactRequestView = object$1({
|
|
8142
8210
|
id: Ulid,
|
|
@@ -8162,7 +8230,8 @@ var init_consent$1 = __esmMin((() => {
|
|
|
8162
8230
|
}),
|
|
8163
8231
|
text: string$1().max(LIMITS.requestChars),
|
|
8164
8232
|
at: Millis,
|
|
8165
|
-
exp: Millis
|
|
8233
|
+
exp: Millis,
|
|
8234
|
+
...Actions
|
|
8166
8235
|
});
|
|
8167
8236
|
AgentInvitationRequest = strictObject({
|
|
8168
8237
|
kind: literal("agent-invitation"),
|
|
@@ -8170,14 +8239,16 @@ var init_consent$1 = __esmMin((() => {
|
|
|
8170
8239
|
cid: ConvId,
|
|
8171
8240
|
from: ParticipantId,
|
|
8172
8241
|
to: ParticipantId,
|
|
8173
|
-
at: Millis
|
|
8242
|
+
at: Millis,
|
|
8243
|
+
...Actions
|
|
8174
8244
|
});
|
|
8175
8245
|
ContactSuggestion = object$1({
|
|
8176
8246
|
id: Ulid,
|
|
8177
8247
|
kind: literal("suggestion"),
|
|
8178
8248
|
agent: SessionName,
|
|
8179
8249
|
email: Email,
|
|
8180
|
-
at: Millis
|
|
8250
|
+
at: Millis,
|
|
8251
|
+
...Actions
|
|
8181
8252
|
});
|
|
8182
8253
|
HeldRequest = union$1([
|
|
8183
8254
|
AskRequest,
|
|
@@ -8185,13 +8256,6 @@ var init_consent$1 = __esmMin((() => {
|
|
|
8185
8256
|
ContactSuggestion,
|
|
8186
8257
|
AgentInvitationRequest
|
|
8187
8258
|
]);
|
|
8188
|
-
RequestAnswer = _enum([
|
|
8189
|
-
"once",
|
|
8190
|
-
"always",
|
|
8191
|
-
"accept",
|
|
8192
|
-
"decline",
|
|
8193
|
-
"block"
|
|
8194
|
-
]);
|
|
8195
8259
|
RequestText = string$1().min(1).refine((text) => text.length <= LIMITS.requestChars, { message: `at most ${LIMITS.requestChars} UTF-16 code units` });
|
|
8196
8260
|
PersonReach = object$1({
|
|
8197
8261
|
person: PersonId,
|
|
@@ -8203,14 +8267,98 @@ var init_consent$1 = __esmMin((() => {
|
|
|
8203
8267
|
RequestAnswerParams = strictObject({
|
|
8204
8268
|
id: Ulid,
|
|
8205
8269
|
answer: RequestAnswer,
|
|
8206
|
-
all: boolean().optional()
|
|
8207
|
-
|
|
8270
|
+
all: boolean().optional(),
|
|
8271
|
+
token: ActionToken.optional()
|
|
8272
|
+
}).refine((p) => p.token === void 0 || p.all !== true, "an action token answers one request: drop all");
|
|
8208
8273
|
ContactRequestParams = strictObject({
|
|
8209
8274
|
email: Email,
|
|
8210
8275
|
text: RequestText,
|
|
8211
8276
|
suggestion: Ulid.optional()
|
|
8212
8277
|
});
|
|
8278
|
+
ReachGroupId = _enum(["message", "ask"]);
|
|
8279
|
+
ReachValue = _enum([
|
|
8280
|
+
"open",
|
|
8281
|
+
"ask",
|
|
8282
|
+
"never"
|
|
8283
|
+
]);
|
|
8284
|
+
ReachOption = object$1({
|
|
8285
|
+
value: ReachValue,
|
|
8286
|
+
label: string$1().max(40),
|
|
8287
|
+
description: string$1().max(300)
|
|
8288
|
+
});
|
|
8289
|
+
ReachGroup = object$1({
|
|
8290
|
+
id: ReachGroupId,
|
|
8291
|
+
label: string$1().max(80),
|
|
8292
|
+
options: array(ReachOption).length(3),
|
|
8293
|
+
value: ReachValue.nullable(),
|
|
8294
|
+
lapsed: ReachValue.optional()
|
|
8295
|
+
});
|
|
8296
|
+
ReachSnapshot = object$1({
|
|
8297
|
+
revision: string$1().min(1).max(64),
|
|
8298
|
+
available: boolean(),
|
|
8299
|
+
groups: array(ReachGroup).length(2)
|
|
8300
|
+
});
|
|
8301
|
+
ReachSetParams = strictObject({
|
|
8302
|
+
revision: string$1().min(1).max(64),
|
|
8303
|
+
changes: strictObject({
|
|
8304
|
+
message: ReachValue.optional(),
|
|
8305
|
+
ask: ReachValue.optional()
|
|
8306
|
+
})
|
|
8307
|
+
});
|
|
8308
|
+
REACH_QUESTIONS = [{
|
|
8309
|
+
id: "message",
|
|
8310
|
+
label: "Who can message you",
|
|
8311
|
+
options: [
|
|
8312
|
+
{
|
|
8313
|
+
value: "open",
|
|
8314
|
+
label: "Open",
|
|
8315
|
+
description: "Anyone outside your org may message you."
|
|
8316
|
+
},
|
|
8317
|
+
{
|
|
8318
|
+
value: "ask",
|
|
8319
|
+
label: "Ask me first",
|
|
8320
|
+
description: "People outside your org send a message request first, and you accept or decline it. People you have accepted may message you."
|
|
8321
|
+
},
|
|
8322
|
+
{
|
|
8323
|
+
value: "never",
|
|
8324
|
+
label: "Never",
|
|
8325
|
+
description: "No one outside your org may message you or send you a request. Your org, and people you have let message you, still can."
|
|
8326
|
+
}
|
|
8327
|
+
]
|
|
8328
|
+
}, {
|
|
8329
|
+
id: "ask",
|
|
8330
|
+
label: "How agents may ask yours",
|
|
8331
|
+
options: [
|
|
8332
|
+
{
|
|
8333
|
+
value: "open",
|
|
8334
|
+
label: "Open",
|
|
8335
|
+
description: "Your teammates' agents may ask your agents without asking you. Their requests run guarded."
|
|
8336
|
+
},
|
|
8337
|
+
{
|
|
8338
|
+
value: "ask",
|
|
8339
|
+
label: "Ask me first",
|
|
8340
|
+
description: "Each request from a teammate's agent to yours waits for your answer."
|
|
8341
|
+
},
|
|
8342
|
+
{
|
|
8343
|
+
value: "never",
|
|
8344
|
+
label: "Never",
|
|
8345
|
+
description: "Your teammates' agents may not ask yours. Agents of people outside your org never may."
|
|
8346
|
+
}
|
|
8347
|
+
]
|
|
8348
|
+
}];
|
|
8213
8349
|
CONSENT_METHODS = {
|
|
8350
|
+
"reach.get": {
|
|
8351
|
+
params: strictObject({}),
|
|
8352
|
+
result: ReachSnapshot
|
|
8353
|
+
},
|
|
8354
|
+
"reach.set": {
|
|
8355
|
+
params: ReachSetParams,
|
|
8356
|
+
result: ReachSnapshot
|
|
8357
|
+
},
|
|
8358
|
+
"reach.set.preview": {
|
|
8359
|
+
params: ReachSetParams,
|
|
8360
|
+
result: object$1({ sentence: string$1().max(500) })
|
|
8361
|
+
},
|
|
8214
8362
|
"grant.list": {
|
|
8215
8363
|
params: strictObject({ subject: GrantTarget.optional() }),
|
|
8216
8364
|
result: object$1({
|
|
@@ -8391,6 +8539,7 @@ var init_jelly$2 = __esmMin((() => {
|
|
|
8391
8539
|
}).optional(),
|
|
8392
8540
|
line: string$1().max(120).optional(),
|
|
8393
8541
|
device: NoticeDevice.optional(),
|
|
8542
|
+
key: string$1().regex(/^task:[0-9A-HJKMNP-TV-Z]{26}$/, "task:<task id>").optional(),
|
|
8394
8543
|
at: Millis
|
|
8395
8544
|
});
|
|
8396
8545
|
NoticeCounts = object$1({ requests: number$1().int().nonnegative() });
|
|
@@ -8461,7 +8610,8 @@ var init_jelly$2 = __esmMin((() => {
|
|
|
8461
8610
|
}),
|
|
8462
8611
|
result: object$1({
|
|
8463
8612
|
relay: _enum(["armed", "pending"]),
|
|
8464
|
-
awaiting: number$1().int().nonnegative()
|
|
8613
|
+
awaiting: number$1().int().nonnegative(),
|
|
8614
|
+
dms: number$1().int().nonnegative()
|
|
8465
8615
|
})
|
|
8466
8616
|
},
|
|
8467
8617
|
"wake.disarm": {
|
|
@@ -8506,6 +8656,7 @@ var init_conversation_views = __esmMin((() => {
|
|
|
8506
8656
|
init_common();
|
|
8507
8657
|
init_conversation();
|
|
8508
8658
|
init_a2a();
|
|
8659
|
+
init_shapes();
|
|
8509
8660
|
Count$2 = number$1().int().nonnegative().safe();
|
|
8510
8661
|
Seq$1 = number$1().int().nonnegative().safe();
|
|
8511
8662
|
Name = string$1().max(200);
|
|
@@ -8581,7 +8732,11 @@ var init_conversation_views = __esmMin((() => {
|
|
|
8581
8732
|
});
|
|
8582
8733
|
TaskView = object$1({
|
|
8583
8734
|
id: Ulid,
|
|
8584
|
-
state: TaskState
|
|
8735
|
+
state: TaskState,
|
|
8736
|
+
cancel: strictObject({
|
|
8737
|
+
name: literal("cancel"),
|
|
8738
|
+
token: ActionToken
|
|
8739
|
+
}).optional()
|
|
8585
8740
|
});
|
|
8586
8741
|
EventView = object$1({
|
|
8587
8742
|
cid: ConvId,
|
|
@@ -8740,6 +8895,11 @@ var init_conversation_views = __esmMin((() => {
|
|
|
8740
8895
|
object$1({
|
|
8741
8896
|
type: literal("gap"),
|
|
8742
8897
|
pos: Seq$1
|
|
8898
|
+
}),
|
|
8899
|
+
object$1({
|
|
8900
|
+
type: literal("task"),
|
|
8901
|
+
pos: Seq$1,
|
|
8902
|
+
task: PersonTask
|
|
8743
8903
|
})
|
|
8744
8904
|
]).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" });
|
|
8745
8905
|
}));
|
|
@@ -8855,7 +9015,12 @@ var init_conversations = __esmMin((() => {
|
|
|
8855
9015
|
at: Millis,
|
|
8856
9016
|
cid: ConvId.optional(),
|
|
8857
9017
|
agent: SessionName.optional(),
|
|
8858
|
-
state: _enum([
|
|
9018
|
+
state: _enum([
|
|
9019
|
+
"held",
|
|
9020
|
+
"pending-delivery",
|
|
9021
|
+
"resend",
|
|
9022
|
+
"outdated"
|
|
9023
|
+
])
|
|
8859
9024
|
});
|
|
8860
9025
|
ConvListParams = strictObject({
|
|
8861
9026
|
key: Key,
|
|
@@ -9497,16 +9662,47 @@ var init_ipc = __esmMin((() => {
|
|
|
9497
9662
|
message: strictObject({ parts: array(Part$1).min(1).max(LIMITS.partsPerMessage) }).optional(),
|
|
9498
9663
|
artifact: Artifact.optional(),
|
|
9499
9664
|
append: boolean().optional(),
|
|
9500
|
-
lastChunk: boolean().optional()
|
|
9501
|
-
|
|
9665
|
+
lastChunk: boolean().optional(),
|
|
9666
|
+
signIn: strictObject({ tool: string$1().min(1).max(TASK_SIGN_IN_TOOL_CHARS) }).optional()
|
|
9667
|
+
}).refine((p) => p.signIn === void 0 || p.state === "TASK_STATE_AUTH_REQUIRED", "signIn goes with TASK_STATE_AUTH_REQUIRED"),
|
|
9502
9668
|
result: TaskRecord
|
|
9503
9669
|
},
|
|
9504
|
-
"task.
|
|
9670
|
+
"task.question": {
|
|
9505
9671
|
params: strictObject({
|
|
9506
9672
|
key: SessionKey,
|
|
9507
9673
|
taskId: Ulid,
|
|
9508
|
-
|
|
9674
|
+
question: TaskQuestion.nullable()
|
|
9675
|
+
}),
|
|
9676
|
+
result: object$1({ ok: literal(true) })
|
|
9677
|
+
},
|
|
9678
|
+
"tasks.list": {
|
|
9679
|
+
params: strictObject({
|
|
9680
|
+
role: _enum(["requester", "executor"]).optional(),
|
|
9681
|
+
state: TaskState.optional(),
|
|
9682
|
+
session: SessionName.optional().describe("only this agent's tasks"),
|
|
9683
|
+
cursor: string$1().min(1).max(200).optional().describe("opaque; from a previous nextCursor"),
|
|
9684
|
+
limit: number$1().int().min(1).max(100).optional()
|
|
9685
|
+
}),
|
|
9686
|
+
result: object$1({
|
|
9687
|
+
tasks: array(PersonTask),
|
|
9688
|
+
nextCursor: string$1().max(200).optional().describe("absent when there are no more pages"),
|
|
9689
|
+
total: number$1().int().nonnegative()
|
|
9690
|
+
})
|
|
9691
|
+
},
|
|
9692
|
+
"tasks.get": {
|
|
9693
|
+
params: strictObject({
|
|
9694
|
+
taskId: Ulid,
|
|
9695
|
+
role: _enum(["requester", "executor"]).optional()
|
|
9509
9696
|
}),
|
|
9697
|
+
result: PersonTask
|
|
9698
|
+
},
|
|
9699
|
+
"task.cancel": {
|
|
9700
|
+
params: strictObject({
|
|
9701
|
+
key: SessionKey.optional(),
|
|
9702
|
+
taskId: Ulid,
|
|
9703
|
+
reason: string$1().max(1e3).optional(),
|
|
9704
|
+
token: ActionToken.optional()
|
|
9705
|
+
}).refine((p) => p.key === void 0 !== (p.token === void 0), "give exactly one of key or token"),
|
|
9510
9706
|
result: TaskRecord
|
|
9511
9707
|
},
|
|
9512
9708
|
"events.subscribe": {
|
|
@@ -9659,7 +9855,8 @@ var init_ipc = __esmMin((() => {
|
|
|
9659
9855
|
"task.list",
|
|
9660
9856
|
"task.get",
|
|
9661
9857
|
"task.update",
|
|
9662
|
-
"task.cancel"
|
|
9858
|
+
"task.cancel",
|
|
9859
|
+
"task.question"
|
|
9663
9860
|
];
|
|
9664
9861
|
HUMAN_METHODS = [
|
|
9665
9862
|
...conversationTier("human"),
|
|
@@ -9668,6 +9865,9 @@ var init_ipc = __esmMin((() => {
|
|
|
9668
9865
|
"grant.list",
|
|
9669
9866
|
"grant.set",
|
|
9670
9867
|
"grant.set.preview",
|
|
9868
|
+
"reach.get",
|
|
9869
|
+
"reach.set",
|
|
9870
|
+
"reach.set.preview",
|
|
9671
9871
|
"request.list",
|
|
9672
9872
|
"request.answer",
|
|
9673
9873
|
"request.answer.preview",
|
|
@@ -9677,6 +9877,8 @@ var init_ipc = __esmMin((() => {
|
|
|
9677
9877
|
"notice.subscribe",
|
|
9678
9878
|
"notice.list",
|
|
9679
9879
|
"notice.ack",
|
|
9880
|
+
"tasks.list",
|
|
9881
|
+
"tasks.get",
|
|
9680
9882
|
"device.approve.preview",
|
|
9681
9883
|
"device.remove.preview",
|
|
9682
9884
|
"identity.replace.preview",
|
|
@@ -9842,7 +10044,8 @@ var init_conv_frames = __esmMin((() => {
|
|
|
9842
10044
|
ConvCapabilitiesFrame = strictObject({
|
|
9843
10045
|
t: literal("conv.capabilities"),
|
|
9844
10046
|
req: Req,
|
|
9845
|
-
outdated: array(PersonId).max(LIMITS.convOpParticipants)
|
|
10047
|
+
outdated: array(PersonId).max(LIMITS.convOpParticipants),
|
|
10048
|
+
unknown: array(PersonId).min(1).max(LIMITS.convOpParticipants).optional()
|
|
9846
10049
|
});
|
|
9847
10050
|
ConvPushFrame = union$1([strictObject({
|
|
9848
10051
|
t: literal("conv.push"),
|
|
@@ -10055,6 +10258,11 @@ var init_agent_tools = __esmMin((() => {
|
|
|
10055
10258
|
titleAuthor: Author$1.optional().describe("With title: who wrote the request; ours when you asked (mine)"),
|
|
10056
10259
|
status: authored("The latest status message").optional(),
|
|
10057
10260
|
statusAuthor: Author$1.optional().describe("With status: who wrote it; ours when you run the task (asked)"),
|
|
10261
|
+
signIn: object$1({
|
|
10262
|
+
tool: authored("The tool the executor named").optional(),
|
|
10263
|
+
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")
|
|
10264
|
+
}).optional().describe("auth_required only: the task waits on a sign-in; the tool was written by the executor, as statusAuthor says"),
|
|
10265
|
+
refusal: object$1({ reason: authored("The executor's reason") }).optional().describe("rejected only: why the executor declined, in its words, as statusAuthor says"),
|
|
10058
10266
|
createdAt: iso$1,
|
|
10059
10267
|
updatedAt: iso$1,
|
|
10060
10268
|
consent: ToolConsentSchema.optional(),
|
|
@@ -10335,7 +10543,7 @@ var init_b64u = __esmMin((() => {
|
|
|
10335
10543
|
// packages/core/dist/version.js
|
|
10336
10544
|
var VERSION;
|
|
10337
10545
|
var init_version$1 = __esmMin((() => {
|
|
10338
|
-
VERSION = "0.
|
|
10546
|
+
VERSION = "0.9.0";
|
|
10339
10547
|
}));
|
|
10340
10548
|
// packages/core/dist/jcs.js
|
|
10341
10549
|
function hasLoneSurrogate(text) {
|
|
@@ -12192,8 +12400,11 @@ var init_jelly_host = __esmMin((() => {
|
|
|
12192
12400
|
"people.search",
|
|
12193
12401
|
"people.get",
|
|
12194
12402
|
"grant.list",
|
|
12403
|
+
"reach.get",
|
|
12195
12404
|
"request.list",
|
|
12196
12405
|
"sessions.list",
|
|
12406
|
+
"tasks.list",
|
|
12407
|
+
"tasks.get",
|
|
12197
12408
|
"notice.subscribe",
|
|
12198
12409
|
"notice.list",
|
|
12199
12410
|
"device.list"
|
|
@@ -13548,7 +13759,25 @@ function verifyConsentGrant(raw, ctx) {
|
|
|
13548
13759
|
}
|
|
13549
13760
|
}
|
|
13550
13761
|
function grantSubjectKey(subject) {
|
|
13551
|
-
return "person" in subject ? `person:${subject.person}` : `conv:${subject.conv}`;
|
|
13762
|
+
return "person" in subject ? `person:${subject.person}` : "conv" in subject ? `conv:${subject.conv}` : `relation:${subject.relation}`;
|
|
13763
|
+
}
|
|
13764
|
+
function reachChoices(outside, org) {
|
|
13765
|
+
const message = outside === void 0 ? void 0 : outside.chat === "open" ? "open" : outside.chat === "blocked" ? "never" : "ask";
|
|
13766
|
+
const ask = org?.ask === "open" ? "open" : org?.ask === "request" ? "ask" : org?.ask === "no" ? "never" : void 0;
|
|
13767
|
+
return {
|
|
13768
|
+
...message ? { message } : {},
|
|
13769
|
+
...ask ? { ask } : {}
|
|
13770
|
+
};
|
|
13771
|
+
}
|
|
13772
|
+
function reachGrant(group, value) {
|
|
13773
|
+
if (group === "message") return {
|
|
13774
|
+
subject: { relation: "outside" },
|
|
13775
|
+
levels: value === "open" ? { chat: "open" } : value === "never" ? { chat: "blocked" } : {}
|
|
13776
|
+
};
|
|
13777
|
+
return {
|
|
13778
|
+
subject: { relation: "org" },
|
|
13779
|
+
levels: { ask: value === "open" ? "open" : value === "never" ? "no" : "request" }
|
|
13780
|
+
};
|
|
13552
13781
|
}
|
|
13553
13782
|
function preferGrant(a, b, current) {
|
|
13554
13783
|
if (a.ts !== b.ts) return a.ts > b.ts ? a : b;
|
|
@@ -13600,8 +13829,24 @@ function levelsOf(grant) {
|
|
|
13600
13829
|
discoverable: grant.discoverable
|
|
13601
13830
|
});
|
|
13602
13831
|
}
|
|
13603
|
-
function
|
|
13832
|
+
function baseLevels(relation, reach) {
|
|
13604
13833
|
const base = DEFAULTS[relation];
|
|
13834
|
+
if (relation === "org") return reach.ask === void 0 ? base : {
|
|
13835
|
+
...base,
|
|
13836
|
+
ask: reach.ask === "open" ? "open" : reach.ask === "never" ? "no" : "request"
|
|
13837
|
+
};
|
|
13838
|
+
if (reach.message === "never") return {
|
|
13839
|
+
...base,
|
|
13840
|
+
chat: "blocked"
|
|
13841
|
+
};
|
|
13842
|
+
if (relation === "stranger" && reach.message === "open") return {
|
|
13843
|
+
...base,
|
|
13844
|
+
chat: "open"
|
|
13845
|
+
};
|
|
13846
|
+
return base;
|
|
13847
|
+
}
|
|
13848
|
+
function effectivePolicy(relation, person, channels, now, reach = {}) {
|
|
13849
|
+
const base = baseLevels(relation, reach);
|
|
13605
13850
|
const channelAsk = channels.map((grant) => grant.ask).filter((level) => level !== void 0);
|
|
13606
13851
|
const channelMail = channels.map((grant) => grant.agentMail).filter((level) => level !== void 0);
|
|
13607
13852
|
const ask = person?.ask ?? (channelAsk.length > 0 ? channelAsk.reduce((a, b) => ASK_RANK[b] > ASK_RANK[a] ? b : a) : void 0);
|
|
@@ -13625,19 +13870,25 @@ function decide(args) {
|
|
|
13625
13870
|
action: "deliver",
|
|
13626
13871
|
consent: "self"
|
|
13627
13872
|
};
|
|
13628
|
-
const policy = effectivePolicy(args.relation, args.grant, args.channels, args.now);
|
|
13873
|
+
const policy = effectivePolicy(args.relation, args.grant, args.channels, args.now, args.reach);
|
|
13629
13874
|
const trusted = (chain) => policy.trustedUntil !== void 0 && chain.every((person) => person === args.sender || person === args.self);
|
|
13630
13875
|
if (inbound.kind === "answer") return {
|
|
13631
13876
|
action: "deliver",
|
|
13632
13877
|
consent: trusted([args.sender]) ? "trusted" : "guarded"
|
|
13633
13878
|
};
|
|
13634
|
-
|
|
13879
|
+
const blocked = policy.chat === "blocked";
|
|
13880
|
+
if (blocked && policy.granted.chat) return {
|
|
13635
13881
|
action: "refuse",
|
|
13636
13882
|
code: "refused"
|
|
13637
13883
|
};
|
|
13638
13884
|
const stranger = args.relation === "stranger";
|
|
13885
|
+
const defaultCode = (outside) => outside && !blocked ? "request_required" : "refused";
|
|
13639
13886
|
switch (inbound.kind) {
|
|
13640
13887
|
case "op":
|
|
13888
|
+
if (blocked) return {
|
|
13889
|
+
action: "refuse",
|
|
13890
|
+
code: "refused"
|
|
13891
|
+
};
|
|
13641
13892
|
if (stranger) return {
|
|
13642
13893
|
action: "refuse",
|
|
13643
13894
|
code: "request_required"
|
|
@@ -13654,9 +13905,13 @@ function decide(args) {
|
|
|
13654
13905
|
};
|
|
13655
13906
|
return {
|
|
13656
13907
|
action: "refuse",
|
|
13657
|
-
code: stranger && !policy.granted.agentMail
|
|
13908
|
+
code: defaultCode(stranger && !policy.granted.agentMail)
|
|
13658
13909
|
};
|
|
13659
13910
|
}
|
|
13911
|
+
if (blocked) return {
|
|
13912
|
+
action: "refuse",
|
|
13913
|
+
code: "refused"
|
|
13914
|
+
};
|
|
13660
13915
|
if (policy.chat === "request_required") return {
|
|
13661
13916
|
action: "refuse",
|
|
13662
13917
|
code: "request_required"
|
|
@@ -13670,7 +13925,11 @@ function decide(args) {
|
|
|
13670
13925
|
consent: "guarded"
|
|
13671
13926
|
};
|
|
13672
13927
|
case "request":
|
|
13673
|
-
if (
|
|
13928
|
+
if (blocked) return {
|
|
13929
|
+
action: "refuse",
|
|
13930
|
+
code: "refused"
|
|
13931
|
+
};
|
|
13932
|
+
if (policy.chat === "request_required") return { action: "hold" };
|
|
13674
13933
|
return policy.chat === "muted" ? {
|
|
13675
13934
|
action: "deliver",
|
|
13676
13935
|
consent: "guarded",
|
|
@@ -13687,7 +13946,7 @@ function decide(args) {
|
|
|
13687
13946
|
if (policy.ask === "request") return { action: "hold" };
|
|
13688
13947
|
return {
|
|
13689
13948
|
action: "refuse",
|
|
13690
|
-
code: !policy.granted.ask && (stranger || args.relation === "contact")
|
|
13949
|
+
code: defaultCode(!policy.granted.ask && (stranger || args.relation === "contact"))
|
|
13691
13950
|
};
|
|
13692
13951
|
}
|
|
13693
13952
|
}
|
|
@@ -13769,8 +14028,8 @@ function verifyContactCard(raw, ctx) {
|
|
|
13769
14028
|
throw asMessagingError(error, "card");
|
|
13770
14029
|
}
|
|
13771
14030
|
}
|
|
13772
|
-
function cardCan(relation, grant, now) {
|
|
13773
|
-
const policy = effectivePolicy(relation, grant, [], now);
|
|
14031
|
+
function cardCan(relation, grant, now, reach = {}) {
|
|
14032
|
+
const policy = effectivePolicy(relation, grant, [], now, reach);
|
|
13774
14033
|
return {
|
|
13775
14034
|
chat: policy.chat === "open" || policy.chat === "muted",
|
|
13776
14035
|
agentMail: policy.agentMail === "open",
|
|
@@ -13916,6 +14175,9 @@ function canTransition(from, to) {
|
|
|
13916
14175
|
function isTerminal(state) {
|
|
13917
14176
|
return TERMINAL_STATES.includes(state);
|
|
13918
14177
|
}
|
|
14178
|
+
function isInterrupted(state) {
|
|
14179
|
+
return INTERRUPTED_STATES.includes(state);
|
|
14180
|
+
}
|
|
13919
14181
|
var NEXT;
|
|
13920
14182
|
var init_task = __esmMin((() => {
|
|
13921
14183
|
init_a2a();
|
|
@@ -14939,6 +15201,7 @@ var init_present = __esmMin((() => {
|
|
|
14939
15201
|
init_errors();
|
|
14940
15202
|
init_peer_text();
|
|
14941
15203
|
init_common();
|
|
15204
|
+
init_ipc();
|
|
14942
15205
|
init_text();
|
|
14943
15206
|
LIMITS.toolTextChars;
|
|
14944
15207
|
createFence({ tag: PEER_FENCE_TAG });
|
|
@@ -16786,7 +17049,7 @@ async function createServer(options, conversations) {
|
|
|
16786
17049
|
method: "hello",
|
|
16787
17050
|
params: {
|
|
16788
17051
|
daemon: "messagingd",
|
|
16789
|
-
version: options.version ?? "0.
|
|
17052
|
+
version: options.version ?? "0.9.0",
|
|
16790
17053
|
protocol: 1,
|
|
16791
17054
|
pid: process.pid,
|
|
16792
17055
|
...options.deployment ? { deployment: options.deployment } : {}
|
|
@@ -18859,7 +19122,7 @@ function taskRow(r) {
|
|
|
18859
19122
|
}
|
|
18860
19123
|
return row;
|
|
18861
19124
|
}
|
|
18862
|
-
var DatabaseSync$1, CONV_JUNK_ALARM_LIMIT, STORE_BASELINE, MIGRATIONS$1, STORE_SCHEMA, kvGet, kvSet, storeNumber, RESET_HINT, TASKS, text$1, num, json, opt, Store;
|
|
19125
|
+
var DatabaseSync$1, CONV_JUNK_ALARM_LIMIT, STORE_BASELINE, MIGRATIONS$1, RELATION$1, relationOf, STORE_SCHEMA, kvGet, kvSet, storeNumber, RESET_HINT, TASKS, text$1, num, json, opt, Store;
|
|
18863
19126
|
var init_store$3 = __esmMin((() => {
|
|
18864
19127
|
init_dist$3();
|
|
18865
19128
|
({DatabaseSync: DatabaseSync$1} = process.getBuiltinModule("node:sqlite"));
|
|
@@ -19168,8 +19431,14 @@ CREATE TABLE IF NOT EXISTS conv_evidence (
|
|
|
19168
19431
|
at INTEGER NOT NULL,
|
|
19169
19432
|
UNIQUE (cid, digest, code)
|
|
19170
19433
|
) STRICT;
|
|
19434
|
+
`,
|
|
19435
|
+
`
|
|
19436
|
+
CREATE TABLE IF NOT EXISTS reach_grants (relation TEXT PRIMARY KEY, grant TEXT NOT NULL) STRICT;
|
|
19437
|
+
CREATE TABLE IF NOT EXISTS reach_reviews (relation TEXT PRIMARY KEY, id TEXT NOT NULL, levels TEXT NOT NULL, at INTEGER NOT NULL) STRICT;
|
|
19171
19438
|
`
|
|
19172
19439
|
];
|
|
19440
|
+
RELATION$1 = "relation:";
|
|
19441
|
+
relationOf = (subject) => subject.startsWith(RELATION$1) ? subject.slice(9) : void 0;
|
|
19173
19442
|
STORE_SCHEMA = 1 + MIGRATIONS$1.length;
|
|
19174
19443
|
kvGet = (db, k) => {
|
|
19175
19444
|
const row = db.prepare("SELECT v FROM kv WHERE k = ?").get(k);
|
|
@@ -19740,6 +20009,16 @@ CREATE TABLE IF NOT EXISTS conv_evidence (
|
|
|
19740
20009
|
contactRequests(person) {
|
|
19741
20010
|
return (person === void 0 ? this.#all("SELECT * FROM contact_requests ORDER BY at, id") : this.#all("SELECT * FROM contact_requests WHERE person = ? ORDER BY at, id", person)).map(contactRequestRow);
|
|
19742
20011
|
}
|
|
20012
|
+
legacyOutgoingRequests(now) {
|
|
20013
|
+
return this.#all(`SELECT t.id AS id, substr(t.room, 4) AS person, t.at AS at FROM transcript t
|
|
20014
|
+
WHERE t.direction = 'out' AND t.room LIKE 'dm:%'
|
|
20015
|
+
AND EXISTS (SELECT 1 FROM chat_sent c WHERE c.line = t.id AND c.stage = 'sent' AND c.held_at IS NOT NULL AND c.exp > ?)
|
|
20016
|
+
ORDER BY t.at, t.id`, now).map((r) => ({
|
|
20017
|
+
id: String(r.id),
|
|
20018
|
+
person: String(r.person),
|
|
20019
|
+
at: Number(r.at)
|
|
20020
|
+
}));
|
|
20021
|
+
}
|
|
19743
20022
|
contactRequestCount() {
|
|
19744
20023
|
return Number(this.#get("SELECT COUNT(*) AS n FROM contact_requests")?.n ?? 0);
|
|
19745
20024
|
}
|
|
@@ -19779,41 +20058,57 @@ CREATE TABLE IF NOT EXISTS conv_evidence (
|
|
|
19779
20058
|
return this.#run("DELETE FROM contact_suggestions WHERE at < ?", before);
|
|
19780
20059
|
}
|
|
19781
20060
|
putGrant(subject, grant) {
|
|
20061
|
+
const relation = relationOf(subject);
|
|
20062
|
+
if (relation !== void 0) {
|
|
20063
|
+
this.#run("INSERT INTO reach_grants (relation, grant) VALUES (?, ?) ON CONFLICT (relation) DO UPDATE SET grant = excluded.grant", relation, JSON.stringify(grant));
|
|
20064
|
+
return;
|
|
20065
|
+
}
|
|
19782
20066
|
this.#run("INSERT INTO grants (subject, grant) VALUES (?, ?) ON CONFLICT (subject) DO UPDATE SET grant = excluded.grant", subject, JSON.stringify(grant));
|
|
19783
20067
|
}
|
|
19784
20068
|
grant(subject) {
|
|
19785
|
-
const
|
|
20069
|
+
const relation = relationOf(subject);
|
|
20070
|
+
const row = relation !== void 0 ? this.#get("SELECT grant FROM reach_grants WHERE relation = ?", relation) : this.#get("SELECT grant FROM grants WHERE subject = ?", subject);
|
|
19786
20071
|
return row === void 0 ? void 0 : JSON.parse(String(row.grant));
|
|
19787
20072
|
}
|
|
19788
20073
|
grants() {
|
|
19789
|
-
return this.#all("SELECT subject, grant FROM grants ORDER BY subject").map((row) => ({
|
|
20074
|
+
return [...this.#all("SELECT subject, grant FROM grants ORDER BY subject").map((row) => ({
|
|
19790
20075
|
subject: String(row.subject),
|
|
19791
20076
|
grant: JSON.parse(String(row.grant))
|
|
19792
|
-
}))
|
|
20077
|
+
})), ...this.#all("SELECT relation, grant FROM reach_grants ORDER BY relation").map((row) => ({
|
|
20078
|
+
subject: `${RELATION$1}${String(row.relation)}`,
|
|
20079
|
+
grant: JSON.parse(String(row.grant))
|
|
20080
|
+
}))];
|
|
19793
20081
|
}
|
|
19794
20082
|
grantCount() {
|
|
19795
20083
|
return Number(this.#get("SELECT COUNT(*) AS n FROM grants")?.n ?? 0);
|
|
19796
20084
|
}
|
|
19797
20085
|
deleteGrant(subject) {
|
|
19798
|
-
|
|
20086
|
+
const relation = relationOf(subject);
|
|
20087
|
+
if (relation !== void 0) this.#run("DELETE FROM reach_grants WHERE relation = ?", relation);
|
|
20088
|
+
else this.#run("DELETE FROM grants WHERE subject = ?", subject);
|
|
19799
20089
|
}
|
|
19800
20090
|
putGrantReview(subject, id, levels, at) {
|
|
19801
|
-
|
|
20091
|
+
const relation = relationOf(subject);
|
|
20092
|
+
this.#run(relation !== void 0 ? "INSERT INTO reach_reviews (relation, id, levels, at) VALUES (?, ?, ?, ?) ON CONFLICT (relation) DO UPDATE SET id = excluded.id, levels = excluded.levels, at = excluded.at" : "INSERT INTO grant_reviews (subject, id, levels, at) VALUES (?, ?, ?, ?) ON CONFLICT (subject) DO UPDATE SET id = excluded.id, levels = excluded.levels, at = excluded.at", relation ?? subject, id, JSON.stringify(levels), at);
|
|
19802
20093
|
}
|
|
19803
20094
|
grantReviews() {
|
|
19804
|
-
|
|
19805
|
-
subject
|
|
19806
|
-
id: String(
|
|
19807
|
-
levels: JSON.parse(String(
|
|
19808
|
-
at: Number(
|
|
19809
|
-
})
|
|
20095
|
+
const row = (subject, r) => ({
|
|
20096
|
+
subject,
|
|
20097
|
+
id: String(r.id),
|
|
20098
|
+
levels: JSON.parse(String(r.levels)),
|
|
20099
|
+
at: Number(r.at)
|
|
20100
|
+
});
|
|
20101
|
+
return [...this.#all("SELECT * FROM grant_reviews ORDER BY at DESC, subject").map((r) => row(String(r.subject), r)), ...this.#all("SELECT * FROM reach_reviews ORDER BY at DESC, relation").map((r) => row(`${RELATION$1}${String(r.relation)}`, r))];
|
|
19810
20102
|
}
|
|
19811
20103
|
grantReview(subject) {
|
|
19812
|
-
const
|
|
20104
|
+
const relation = relationOf(subject);
|
|
20105
|
+
const row = relation !== void 0 ? this.#get("SELECT id FROM reach_reviews WHERE relation = ?", relation) : this.#get("SELECT id FROM grant_reviews WHERE subject = ?", subject);
|
|
19813
20106
|
return row === void 0 ? void 0 : { id: String(row.id) };
|
|
19814
20107
|
}
|
|
19815
20108
|
deleteGrantReview(subject) {
|
|
19816
|
-
|
|
20109
|
+
const relation = relationOf(subject);
|
|
20110
|
+
if (relation !== void 0) this.#run("DELETE FROM reach_reviews WHERE relation = ?", relation);
|
|
20111
|
+
else this.#run("DELETE FROM grant_reviews WHERE subject = ?", subject);
|
|
19817
20112
|
}
|
|
19818
20113
|
sentUndelivered(now) {
|
|
19819
20114
|
return this.#all("SELECT * FROM sent WHERE exp <= ? AND stage IN ('accepted', 'relayed')", now).map(sentRow);
|
|
@@ -19878,12 +20173,13 @@ CREATE TABLE IF NOT EXISTS conv_evidence (
|
|
|
19878
20173
|
if (r.chain !== void 0) this.#run("INSERT OR IGNORE INTO delegations (task_id, role, grants, chain) VALUES (?, ?, ?, ?)", r.task.id, r.role, JSON.stringify(row.grants), JSON.stringify(r.chain));
|
|
19879
20174
|
}
|
|
19880
20175
|
listTasks(filter) {
|
|
19881
|
-
const where = ["
|
|
19882
|
-
const params = [
|
|
20176
|
+
const where = ["1 = 1"];
|
|
20177
|
+
const params = [];
|
|
19883
20178
|
const add = (clause, ...values) => {
|
|
19884
20179
|
where.push(clause);
|
|
19885
20180
|
params.push(...values);
|
|
19886
20181
|
};
|
|
20182
|
+
if (filter.key !== void 0) add("key = ?", filter.key);
|
|
19887
20183
|
if (filter.role !== void 0) add("role = ?", filter.role);
|
|
19888
20184
|
if (filter.state !== void 0) add("state = ?", filter.state);
|
|
19889
20185
|
if (filter.contextId !== void 0) add("context_id = ?", filter.contextId);
|
|
@@ -20613,7 +20909,7 @@ var init_conv_engine = __esmMin((() => {
|
|
|
20613
20909
|
const pending = this.options.store.convPending(cid);
|
|
20614
20910
|
if (rekey.cause === "device" && pending) {
|
|
20615
20911
|
const first = admitConvEvent(parseWire(pending.event));
|
|
20616
|
-
if (first.class === "op" && first.body.op === "rekey" && first.body.cause === "device" && first.body.device === rekey.device) return first.id;
|
|
20912
|
+
if (first.class === "op" && first.body.op === "rekey" && first.body.cause === "device" && first.body.device === rekey.device && (rekey.until === void 0 || first.body.until !== void 0 && first.body.until <= rekey.until)) return first.id;
|
|
20617
20913
|
return await this.#queueRekey(cid, rekey, true);
|
|
20618
20914
|
}
|
|
20619
20915
|
return await this.#queueRekey(cid, rekey, false);
|
|
@@ -21394,12 +21690,13 @@ var init_conv_project = __esmMin((() => {
|
|
|
21394
21690
|
]);
|
|
21395
21691
|
}));
|
|
21396
21692
|
// packages/daemon/dist/conv-ipc.js
|
|
21397
|
-
var DEFERRED_LINES, DEFERRED_MS, HOLD, REPLAY$1, RESPONSE_BYTES, ConversationIpc;
|
|
21693
|
+
var DEFERRED_LINES, DEFERRED_MS, CONTROL_DRAINS, HOLD, REPLAY$1, RESPONSE_BYTES, ConversationIpc;
|
|
21398
21694
|
var init_conv_ipc = __esmMin((() => {
|
|
21399
21695
|
init_dist$3();
|
|
21400
21696
|
init_conv_project();
|
|
21401
21697
|
DEFERRED_LINES = 50;
|
|
21402
21698
|
DEFERRED_MS = 6048e5;
|
|
21699
|
+
CONTROL_DRAINS = 3;
|
|
21403
21700
|
HOLD = {
|
|
21404
21701
|
stage: "held",
|
|
21405
21702
|
code: "context",
|
|
@@ -21440,6 +21737,18 @@ var init_conv_ipc = __esmMin((() => {
|
|
|
21440
21737
|
own: this.options.own().person
|
|
21441
21738
|
});
|
|
21442
21739
|
}
|
|
21740
|
+
taskChanged(side) {
|
|
21741
|
+
this.#ring.push({
|
|
21742
|
+
pos: ++this.#pos,
|
|
21743
|
+
task: {
|
|
21744
|
+
id: side.id,
|
|
21745
|
+
role: side.role
|
|
21746
|
+
}
|
|
21747
|
+
});
|
|
21748
|
+
if (this.#ring.length > REPLAY$1) this.#floor = this.#ring.shift().pos;
|
|
21749
|
+
this.options.put("conv.ipc.pos", String(this.#pos));
|
|
21750
|
+
for (const wake of [...this.#waiters]) wake();
|
|
21751
|
+
}
|
|
21443
21752
|
bind(engine) {
|
|
21444
21753
|
if (this.#engine === engine) return;
|
|
21445
21754
|
this.#unsubscribe?.();
|
|
@@ -21538,7 +21847,7 @@ var init_conv_ipc = __esmMin((() => {
|
|
|
21538
21847
|
return Object.fromEntries(Object.keys(LIVE_CONVERSATION_METHODS).map((method) => [method, async (params, ctx, authority) => {
|
|
21539
21848
|
if (authority?.scope === "host") throw new MessagingError("forbidden", "conversation content needs an action grant");
|
|
21540
21849
|
const name = method;
|
|
21541
|
-
const result = await this.call(name, params, ctx);
|
|
21850
|
+
const result = await this.call(name, params, ctx, authority);
|
|
21542
21851
|
const parsed = LIVE_CONVERSATION_METHODS[name].result.parse(result);
|
|
21543
21852
|
if (Buffer.byteLength(JSON.stringify(parsed)) > RESPONSE_BYTES) throw new MessagingError("too_large", "conversation response exceeds the byte budget");
|
|
21544
21853
|
return parsed;
|
|
@@ -21664,7 +21973,13 @@ var init_conv_ipc = __esmMin((() => {
|
|
|
21664
21973
|
const access = this.#access(engine, cid, scope);
|
|
21665
21974
|
if (access.access === "forbidden") throw new MessagingError("forbidden", "the session cannot read this conversation");
|
|
21666
21975
|
if (access.access === "ask") return HOLD;
|
|
21667
|
-
|
|
21976
|
+
const orgs = new Map();
|
|
21977
|
+
const name = async (p) => {
|
|
21978
|
+
const profile = await this.#name(p);
|
|
21979
|
+
orgs.set(p, profile.org);
|
|
21980
|
+
return profile;
|
|
21981
|
+
};
|
|
21982
|
+
let visible = (await projectEvents(engine, cid, scope.participant, name, (p) => !this.options.blocked(p, orgs.get(p) ?? "none"))).filter((e) => e.seq >= access.since && e.at >= access.after);
|
|
21668
21983
|
if (scope.agent && this.#state(engine, cid, scope).state.agentContext === "none") {
|
|
21669
21984
|
const roots = new Set(visible.filter((e) => e.author.p === scope.participant || e.mentions?.some((m) => "p" in m && m.p === scope.participant)).map((e) => e.thread ?? e.id));
|
|
21670
21985
|
visible = visible.filter((e) => roots.has(e.id) || e.thread !== void 0 && roots.has(e.thread));
|
|
@@ -21747,10 +22062,30 @@ var init_conv_ipc = __esmMin((() => {
|
|
|
21747
22062
|
};
|
|
21748
22063
|
const events = [];
|
|
21749
22064
|
let pos = after;
|
|
21750
|
-
|
|
22065
|
+
const range = this.#ring.filter((i) => i.pos > after);
|
|
22066
|
+
for (const [index, item] of range.entries()) {
|
|
21751
22067
|
pos = item.pos;
|
|
21752
|
-
const c = item.change;
|
|
21753
22068
|
let rendered;
|
|
22069
|
+
if ("task" in item) {
|
|
22070
|
+
const side = item.task;
|
|
22071
|
+
if (scope.key !== void 0 || scope.ctx.tier !== "admin" || !this.options.task) continue;
|
|
22072
|
+
if (range.slice(index + 1).some((later) => "task" in later && later.task.id === side.id && later.task.role === side.role)) continue;
|
|
22073
|
+
const task = await this.options.task(side.id, side.role, scope.ctx, scope.authority);
|
|
22074
|
+
if (!task) continue;
|
|
22075
|
+
rendered = {
|
|
22076
|
+
type: "task",
|
|
22077
|
+
pos,
|
|
22078
|
+
task
|
|
22079
|
+
};
|
|
22080
|
+
if (Buffer.byteLength(JSON.stringify([...events, rendered])) > 520192) {
|
|
22081
|
+
pos = item.pos - 1;
|
|
22082
|
+
break;
|
|
22083
|
+
}
|
|
22084
|
+
events.push(rendered);
|
|
22085
|
+
if (events.length >= (p.limit ?? 50)) break;
|
|
22086
|
+
continue;
|
|
22087
|
+
}
|
|
22088
|
+
const c = item.change;
|
|
21754
22089
|
try {
|
|
21755
22090
|
if (this.#access(engine, c.cid, scope).access !== "allow") continue;
|
|
21756
22091
|
if (c.type === "members.changed") rendered = {
|
|
@@ -21834,7 +22169,7 @@ var init_conv_ipc = __esmMin((() => {
|
|
|
21834
22169
|
result = await read();
|
|
21835
22170
|
return result;
|
|
21836
22171
|
}
|
|
21837
|
-
async call(method, raw, ctx) {
|
|
22172
|
+
async call(method, raw, ctx, authority) {
|
|
21838
22173
|
if (ctx.tier === "agent" && CONVERSATION_TIERS[method] !== "agent") throw new MessagingError("forbidden", "this method is human-only");
|
|
21839
22174
|
const p = LIVE_CONVERSATION_METHODS[method].params.parse(raw);
|
|
21840
22175
|
if (method === "people.get") {
|
|
@@ -21857,7 +22192,10 @@ var init_conv_ipc = __esmMin((() => {
|
|
|
21857
22192
|
seats: engine?.list().filter((c) => c.state?.participants.some((p) => p.p === `${this.options.own().person}/${s.agent}` && p.state === "member")).map((c) => c.cid) ?? []
|
|
21858
22193
|
})) };
|
|
21859
22194
|
}
|
|
21860
|
-
const scope =
|
|
22195
|
+
const scope = {
|
|
22196
|
+
...this.#scope("key" in p ? p.key : void 0, ctx),
|
|
22197
|
+
authority
|
|
22198
|
+
};
|
|
21861
22199
|
const engine = this.#current();
|
|
21862
22200
|
const { cursor: _cursor, ...position } = p;
|
|
21863
22201
|
const query = canonicalize({
|
|
@@ -22125,7 +22463,10 @@ var init_conv_ipc = __esmMin((() => {
|
|
|
22125
22463
|
await this.options.current?.(p.participants.map((s) => participantPerson(s.p)));
|
|
22126
22464
|
}
|
|
22127
22465
|
const { cid, ...fields } = p;
|
|
22128
|
-
|
|
22466
|
+
for (let drains = 0; method !== "conv.meta" && engine.pending(cid).length > 0; drains++) {
|
|
22467
|
+
if (drains === CONTROL_DRAINS) throw new MessagingError("conv_conflict", "the conversation is busy sending; try again");
|
|
22468
|
+
await engine.flush(cid);
|
|
22469
|
+
}
|
|
22129
22470
|
if (method === "conv.meta") await engine.queueMeta(cid, p.meta);
|
|
22130
22471
|
else engine.control(cid, {
|
|
22131
22472
|
op: method.slice(5),
|
|
@@ -23118,7 +23459,11 @@ function fitPresence(sessions, baseBytes, limit) {
|
|
|
23118
23459
|
var FEATURES;
|
|
23119
23460
|
var init_directory$1 = __esmMin((() => {
|
|
23120
23461
|
init_dist$3();
|
|
23121
|
-
FEATURES = [
|
|
23462
|
+
FEATURES = [
|
|
23463
|
+
"tasks",
|
|
23464
|
+
"conversations",
|
|
23465
|
+
"reach"
|
|
23466
|
+
];
|
|
23122
23467
|
}));
|
|
23123
23468
|
// packages/daemon/dist/delegation.js
|
|
23124
23469
|
function parentChain(store, key, p) {
|
|
@@ -23973,6 +24318,19 @@ var init_directory_identity = __esmMin((() => {
|
|
|
23973
24318
|
const head = this.#head;
|
|
23974
24319
|
return head !== void 0 && this.#options.now() - head.sth.ts > maxAgeMs + LIMITS.epochHeartbeatMs;
|
|
23975
24320
|
}
|
|
24321
|
+
async freshen(persons, batch = LIMITS.dirLookupPersons) {
|
|
24322
|
+
const size1 = Math.max(1, Math.min(batch, LIMITS.dirLookupPersons));
|
|
24323
|
+
const now = this.#options.now();
|
|
24324
|
+
const size = this.#head?.sth.size ?? 0;
|
|
24325
|
+
const stale = [...new Set(persons)].filter((person) => {
|
|
24326
|
+
if (!isHosted(person)) return false;
|
|
24327
|
+
const held = this.#persons.get(person);
|
|
24328
|
+
return !held || now - held.fetchedAt >= LIMITS.dirFreshMs || held.size < size;
|
|
24329
|
+
});
|
|
24330
|
+
if (stale.length === 0 && !this.#headOlderThan(LIMITS.dirFreshMs)) return;
|
|
24331
|
+
await this.#latest();
|
|
24332
|
+
for (let i = 0; i < stale.length; i += size1) await this.#fetch(stale.slice(i, i + size1));
|
|
24333
|
+
}
|
|
23976
24334
|
async profile(person) {
|
|
23977
24335
|
if (!isHosted(person)) throw new MessagingError("not_found", "no such person in this realm");
|
|
23978
24336
|
await this.devices(person);
|
|
@@ -25138,8 +25496,10 @@ var init_jelly$1 = __esmMin((() => {
|
|
|
25138
25496
|
this.#deps = deps;
|
|
25139
25497
|
}
|
|
25140
25498
|
authorize(call) {
|
|
25141
|
-
const
|
|
25142
|
-
|
|
25499
|
+
const params = call.params !== null && typeof call.params === "object" ? call.params : void 0;
|
|
25500
|
+
const sessionCall = params !== void 0 && typeof params.key === "string";
|
|
25501
|
+
const tokenCall = params !== void 0 && Object.hasOwn(params, "token");
|
|
25502
|
+
if (call.ctx.tier === "agent" || AGENT.has(call.method) && !tokenCall && (!Object.hasOwn(CONVERSATION_METHODS, call.method) || sessionCall)) return void 0;
|
|
25143
25503
|
const refuse = (error) => {
|
|
25144
25504
|
this.#deps.log("warn", "jelly.grant.refused", {
|
|
25145
25505
|
method: call.method,
|
|
@@ -25181,7 +25541,9 @@ var init_jelly$1 = __esmMin((() => {
|
|
|
25181
25541
|
});
|
|
25182
25542
|
return {
|
|
25183
25543
|
scope: grant.scope,
|
|
25184
|
-
expiresAt: (grant.exp + 5) * 1e3
|
|
25544
|
+
expiresAt: (grant.exp + 5) * 1e3,
|
|
25545
|
+
...grant.dev !== void 0 ? { dev: grant.dev } : {},
|
|
25546
|
+
...grant.mbr !== void 0 ? { mbr: grant.mbr } : {}
|
|
25185
25547
|
};
|
|
25186
25548
|
}
|
|
25187
25549
|
ticket(p) {
|
|
@@ -25529,7 +25891,7 @@ function deviceLine(d) {
|
|
|
25529
25891
|
const line = d.change === "added" ? `New device on your account: ${what}, ${vouchWords(d)}.` : d.change === "vouched" ? `${what} on your account is now vouched by Jelly ID: ${vouchWords(d)}.` : d.change === "replaced" ? `'${d.replaces?.label ?? "a device"}' was replaced by ${what}, ${vouchWords(d)}.` : `${what} was removed from your account.`;
|
|
25530
25892
|
return line.length <= 120 ? line : `${line.slice(0, 119)}…`;
|
|
25531
25893
|
}
|
|
25532
|
-
var ALERT_TEXT, REPLAY, Notices;
|
|
25894
|
+
var ALERT_TEXT, TASK_SOURCE, REPLAY, Notices;
|
|
25533
25895
|
var init_notices = __esmMin((() => {
|
|
25534
25896
|
init_dist$3();
|
|
25535
25897
|
ALERT_TEXT = {
|
|
@@ -25537,6 +25899,7 @@ var init_notices = __esmMin((() => {
|
|
|
25537
25899
|
restored: "This device was restored from an older copy: it publishes no keys until it is replaced.",
|
|
25538
25900
|
directory: "The key directory gave inconsistent answers about your devices; the evidence is kept."
|
|
25539
25901
|
};
|
|
25902
|
+
TASK_SOURCE = "task:";
|
|
25540
25903
|
REPLAY = 500;
|
|
25541
25904
|
Notices = class {
|
|
25542
25905
|
#host;
|
|
@@ -25554,6 +25917,15 @@ var init_notices = __esmMin((() => {
|
|
|
25554
25917
|
at: row.at
|
|
25555
25918
|
});
|
|
25556
25919
|
}
|
|
25920
|
+
task(row) {
|
|
25921
|
+
this.#file({
|
|
25922
|
+
id: `m_task${row.taskId}`,
|
|
25923
|
+
category: "message",
|
|
25924
|
+
person: row.person,
|
|
25925
|
+
source: `${TASK_SOURCE}${row.taskId}`,
|
|
25926
|
+
at: row.at
|
|
25927
|
+
});
|
|
25928
|
+
}
|
|
25557
25929
|
alert(kind, at) {
|
|
25558
25930
|
this.#file({
|
|
25559
25931
|
id: `a_${kind.replace(/_/g, "")}${at}`,
|
|
@@ -25586,6 +25958,7 @@ var init_notices = __esmMin((() => {
|
|
|
25586
25958
|
notice: {
|
|
25587
25959
|
id: row.id,
|
|
25588
25960
|
category: row.category,
|
|
25961
|
+
...row.source.startsWith(TASK_SOURCE) ? { key: `task:${row.source.slice(5)}` } : {},
|
|
25589
25962
|
at: row.at
|
|
25590
25963
|
}
|
|
25591
25964
|
});
|
|
@@ -25659,6 +26032,7 @@ var init_notices = __esmMin((() => {
|
|
|
25659
26032
|
org: own ? "same" : "none"
|
|
25660
26033
|
};
|
|
25661
26034
|
}
|
|
26035
|
+
if (row.category === "message" && row.source.startsWith(TASK_SOURCE)) notice.key = `task:${row.source.slice(5)}`;
|
|
25662
26036
|
if (row.category === "alert" && row.source.startsWith("device:")) {
|
|
25663
26037
|
const device = this.#host.device?.(Number(row.source.slice(7)));
|
|
25664
26038
|
if (device) notice.device = device;
|
|
@@ -25671,6 +26045,67 @@ var init_notices = __esmMin((() => {
|
|
|
25671
26045
|
}
|
|
25672
26046
|
};
|
|
25673
26047
|
}));
|
|
26048
|
+
// packages/daemon/dist/task-view.js
|
|
26049
|
+
function plainCapped(text, max, singleLine) {
|
|
26050
|
+
let budget = max;
|
|
26051
|
+
for (;;) {
|
|
26052
|
+
const out = cleanPeerText(text, {
|
|
26053
|
+
singleLine,
|
|
26054
|
+
maxChars: budget
|
|
26055
|
+
}).trim();
|
|
26056
|
+
if (out.length <= max) return out.length > 0 ? out : void 0;
|
|
26057
|
+
budget = Math.max(0, budget - (out.length - max));
|
|
26058
|
+
}
|
|
26059
|
+
}
|
|
26060
|
+
function executorWords(record) {
|
|
26061
|
+
const message = record.task.status.message;
|
|
26062
|
+
return message !== void 0 && (record.role === "executor" || message.metadata?.[URI.provenance] !== void 0);
|
|
26063
|
+
}
|
|
26064
|
+
function signInTool(record) {
|
|
26065
|
+
if (!executorWords(record)) return void 0;
|
|
26066
|
+
const value = record.task.status.message?.metadata?.[URI.signIn];
|
|
26067
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
26068
|
+
const tool = value.tool;
|
|
26069
|
+
return typeof tool === "string" ? plainCapped(tool, TASK_SIGN_IN_TOOL_CHARS, true) : void 0;
|
|
26070
|
+
}
|
|
26071
|
+
function refusalReason(record) {
|
|
26072
|
+
if (!executorWords(record)) return void 0;
|
|
26073
|
+
return plainCapped((record.task.status.message?.parts ?? []).flatMap((part) => typeof part.text === "string" ? [part.text] : []).join("\n"), TASK_REFUSAL_CHARS, false);
|
|
26074
|
+
}
|
|
26075
|
+
function withTaskView(record, me, named) {
|
|
26076
|
+
const view = { ...record };
|
|
26077
|
+
delete view.agent;
|
|
26078
|
+
delete view.person;
|
|
26079
|
+
delete view.org;
|
|
26080
|
+
delete view.signIn;
|
|
26081
|
+
delete view.refusal;
|
|
26082
|
+
delete view.question;
|
|
26083
|
+
if (record.peer.agent !== void 0) view.agent = record.peer.agent;
|
|
26084
|
+
if (named !== void 0) {
|
|
26085
|
+
view.person = {
|
|
26086
|
+
id: record.peer.person,
|
|
26087
|
+
name: named.name.slice(0, 200)
|
|
26088
|
+
};
|
|
26089
|
+
view.org = named.org;
|
|
26090
|
+
}
|
|
26091
|
+
const state = record.task.status.state;
|
|
26092
|
+
if (state === "TASK_STATE_AUTH_REQUIRED") {
|
|
26093
|
+
const mine = record.role === "executor" || me !== void 0 && record.peer.person === me;
|
|
26094
|
+
const tool = signInTool(record);
|
|
26095
|
+
view.signIn = {
|
|
26096
|
+
...tool !== void 0 ? { tool } : {},
|
|
26097
|
+
by: mine ? "you" : "them"
|
|
26098
|
+
};
|
|
26099
|
+
}
|
|
26100
|
+
if (state === "TASK_STATE_REJECTED") {
|
|
26101
|
+
const reason = refusalReason(record);
|
|
26102
|
+
if (reason !== void 0) view.refusal = { reason };
|
|
26103
|
+
}
|
|
26104
|
+
return view;
|
|
26105
|
+
}
|
|
26106
|
+
var init_task_view = __esmMin((() => {
|
|
26107
|
+
init_dist$3();
|
|
26108
|
+
}));
|
|
25674
26109
|
// packages/daemon/dist/realm/counterpart.js
|
|
25675
26110
|
function successors(realm, recorded) {
|
|
25676
26111
|
const chain = [recorded];
|
|
@@ -26667,7 +27102,117 @@ var init_wake_bridge = __esmMin((() => {
|
|
|
26667
27102
|
};
|
|
26668
27103
|
AnswerTooLarge = class extends Error {};
|
|
26669
27104
|
}));
|
|
27105
|
+
// packages/daemon/dist/action-tokens.js
|
|
27106
|
+
function actionView(ctx, authority, sessionKey) {
|
|
27107
|
+
if (ctx.tier !== "admin" || sessionKey !== void 0 || authority?.scope === "host") return void 0;
|
|
27108
|
+
return {
|
|
27109
|
+
connection: ctx.id,
|
|
27110
|
+
...authority?.dev !== void 0 ? { dev: authority.dev } : {},
|
|
27111
|
+
...authority?.mbr !== void 0 ? { mbr: authority.mbr } : {}
|
|
27112
|
+
};
|
|
27113
|
+
}
|
|
27114
|
+
function taskCancelAction(tokens, task, view) {
|
|
27115
|
+
if (view === void 0 || task.role !== "requester" || task.ended) return void 0;
|
|
27116
|
+
return {
|
|
27117
|
+
name: "cancel",
|
|
27118
|
+
token: tokens.offer(view, "cancel", `task:${task.id}`)
|
|
27119
|
+
};
|
|
27120
|
+
}
|
|
27121
|
+
var ACTION_TOKEN_TTL_MS, ACTION_TOKENS_TOTAL, viewKey, offerKey, ActionTokens;
|
|
27122
|
+
var init_action_tokens = __esmMin((() => {
|
|
27123
|
+
init_dist$3();
|
|
27124
|
+
ACTION_TOKEN_TTL_MS = 6e5;
|
|
27125
|
+
ACTION_TOKENS_TOTAL = 4096;
|
|
27126
|
+
viewKey = (view) => JSON.stringify([
|
|
27127
|
+
view.connection,
|
|
27128
|
+
view.dev ?? null,
|
|
27129
|
+
view.mbr ?? null
|
|
27130
|
+
]);
|
|
27131
|
+
offerKey = (view, name, target) => JSON.stringify([
|
|
27132
|
+
view,
|
|
27133
|
+
name,
|
|
27134
|
+
target
|
|
27135
|
+
]);
|
|
27136
|
+
ActionTokens = class {
|
|
27137
|
+
now;
|
|
27138
|
+
limits;
|
|
27139
|
+
#held = new Map();
|
|
27140
|
+
#offers = new Map();
|
|
27141
|
+
#perView = new Map();
|
|
27142
|
+
constructor(now, limits = {
|
|
27143
|
+
perView: 256,
|
|
27144
|
+
total: ACTION_TOKENS_TOTAL,
|
|
27145
|
+
ttlMs: ACTION_TOKEN_TTL_MS
|
|
27146
|
+
}) {
|
|
27147
|
+
this.now = now;
|
|
27148
|
+
this.limits = limits;
|
|
27149
|
+
}
|
|
27150
|
+
get size() {
|
|
27151
|
+
return this.#held.size;
|
|
27152
|
+
}
|
|
27153
|
+
offer(view, name, target) {
|
|
27154
|
+
const now = this.now();
|
|
27155
|
+
const key = viewKey(view);
|
|
27156
|
+
const offered = this.#offers.get(offerKey(key, name, target));
|
|
27157
|
+
if (offered !== void 0) {
|
|
27158
|
+
const held = this.#held.get(offered);
|
|
27159
|
+
if (held !== void 0 && held.exp - now > this.limits.ttlMs / 2) return offered;
|
|
27160
|
+
}
|
|
27161
|
+
this.sweep();
|
|
27162
|
+
while ((this.#perView.get(key) ?? 0) >= this.limits.perView && this.#dropOldest((h) => h.view === key));
|
|
27163
|
+
while (this.#held.size >= this.limits.total && this.#dropOldest(() => true));
|
|
27164
|
+
const token = randomBytes(32).toString("base64url");
|
|
27165
|
+
this.#held.set(token, {
|
|
27166
|
+
name,
|
|
27167
|
+
target,
|
|
27168
|
+
view: key,
|
|
27169
|
+
connection: view.connection,
|
|
27170
|
+
exp: now + this.limits.ttlMs
|
|
27171
|
+
});
|
|
27172
|
+
this.#offers.set(offerKey(key, name, target), token);
|
|
27173
|
+
this.#perView.set(key, (this.#perView.get(key) ?? 0) + 1);
|
|
27174
|
+
return token;
|
|
27175
|
+
}
|
|
27176
|
+
redeem(token, want) {
|
|
27177
|
+
const held = this.#held.get(token);
|
|
27178
|
+
if (held !== void 0) this.#delete(token, held);
|
|
27179
|
+
this.#match(held, want);
|
|
27180
|
+
}
|
|
27181
|
+
check(token, want) {
|
|
27182
|
+
this.#match(this.#held.get(token), want);
|
|
27183
|
+
}
|
|
27184
|
+
disconnected(connection) {
|
|
27185
|
+
for (const [token, held] of [...this.#held]) if (held.connection === connection) this.#delete(token, held);
|
|
27186
|
+
}
|
|
27187
|
+
sweep() {
|
|
27188
|
+
const now = this.now();
|
|
27189
|
+
for (const [token, held] of [...this.#held]) if (held.exp <= now) this.#delete(token, held);
|
|
27190
|
+
}
|
|
27191
|
+
#match(held, want) {
|
|
27192
|
+
if (!(held !== void 0 && held.exp > this.now() && held.name === want.name && held.target === want.target && held.view === viewKey(want.view))) throw new MessagingError("grant_invalid", "the action token is not one this daemon offered for this action, item and view, or it was spent or expired; read the view again");
|
|
27193
|
+
}
|
|
27194
|
+
#dropOldest(which) {
|
|
27195
|
+
for (const [token, held] of this.#held) {
|
|
27196
|
+
if (!which(held)) continue;
|
|
27197
|
+
this.#delete(token, held);
|
|
27198
|
+
return true;
|
|
27199
|
+
}
|
|
27200
|
+
return false;
|
|
27201
|
+
}
|
|
27202
|
+
#delete(token, held) {
|
|
27203
|
+
this.#held.delete(token);
|
|
27204
|
+
const key = offerKey(held.view, held.name, held.target);
|
|
27205
|
+
if (this.#offers.get(key) === token) this.#offers.delete(key);
|
|
27206
|
+
const count = (this.#perView.get(held.view) ?? 1) - 1;
|
|
27207
|
+
if (count > 0) this.#perView.set(held.view, count);
|
|
27208
|
+
else this.#perView.delete(held.view);
|
|
27209
|
+
}
|
|
27210
|
+
};
|
|
27211
|
+
}));
|
|
26670
27212
|
// packages/daemon/dist/consent/grants.js
|
|
27213
|
+
function isRelationKey(key) {
|
|
27214
|
+
return key.startsWith("relation:");
|
|
27215
|
+
}
|
|
26671
27216
|
function levelsFrom(p, now) {
|
|
26672
27217
|
const trustedUntil = p.trustedUntil ?? (p.trust ? now + LIMITS.trustDefaultMs : void 0);
|
|
26673
27218
|
return levelsOf({
|
|
@@ -26718,14 +27263,42 @@ var init_grants = __esmMin((() => {
|
|
|
26718
27263
|
const members = this.#host.participants(cid, event?.seq);
|
|
26719
27264
|
return members.includes(person) && members.includes(me.person);
|
|
26720
27265
|
})),
|
|
27266
|
+
reach: this.reach(),
|
|
26721
27267
|
inbound,
|
|
26722
27268
|
now: this.#host.now()
|
|
26723
27269
|
});
|
|
26724
27270
|
}
|
|
27271
|
+
hides(participant, org) {
|
|
27272
|
+
const slash = participant.indexOf("/");
|
|
27273
|
+
const person = slash === -1 ? participant : participant.slice(0, slash);
|
|
27274
|
+
const { me } = this.#host.joined();
|
|
27275
|
+
if (person === me.person) return false;
|
|
27276
|
+
const grant = this.personGrant(person);
|
|
27277
|
+
if (grant?.chat === "blocked") return true;
|
|
27278
|
+
if (slash !== -1 || org !== "other") return false;
|
|
27279
|
+
return effectivePolicy(this.hasGrant(person) ? "contact" : "stranger", grant, [], this.#host.now(), this.reach()).chat === "blocked";
|
|
27280
|
+
}
|
|
26725
27281
|
personGrant(person) {
|
|
26726
27282
|
const grant = this.#current(grantSubjectKey({ person }));
|
|
26727
27283
|
return grant && levelsOf(grant);
|
|
26728
27284
|
}
|
|
27285
|
+
relationGrant(relation) {
|
|
27286
|
+
const grant = this.#current(grantSubjectKey({ relation }));
|
|
27287
|
+
return grant && levelsOf(grant);
|
|
27288
|
+
}
|
|
27289
|
+
reach() {
|
|
27290
|
+
return reachChoices(this.relationGrant("outside"), this.relationGrant("org"));
|
|
27291
|
+
}
|
|
27292
|
+
relationRecord(relation) {
|
|
27293
|
+
const key = grantSubjectKey({ relation });
|
|
27294
|
+
return {
|
|
27295
|
+
grant: this.#store.grant(key) ?? null,
|
|
27296
|
+
review: this.#store.grantReviews().find(({ subject }) => subject === key) ?? null
|
|
27297
|
+
};
|
|
27298
|
+
}
|
|
27299
|
+
relationReview(relation) {
|
|
27300
|
+
return this.#store.grantReviews().find(({ subject }) => subject === grantSubjectKey({ relation }))?.levels;
|
|
27301
|
+
}
|
|
26729
27302
|
conversationGrants(conversations) {
|
|
26730
27303
|
return conversations.flatMap((conv) => {
|
|
26731
27304
|
const grant = this.#current(grantSubjectKey({ conv }));
|
|
@@ -26751,8 +27324,8 @@ var init_grants = __esmMin((() => {
|
|
|
26751
27324
|
list(p) {
|
|
26752
27325
|
const only = p.subject === void 0 ? void 0 : this.#subjectKey(p.subject, false);
|
|
26753
27326
|
return {
|
|
26754
|
-
grants: this.#all().filter(({ subject }) => only === void 0 || subject === only).map(({ grant }) => this.#view(grant)).sort((a, b) => b.ts - a.ts || (a.id < b.id ? 1 : -1)),
|
|
26755
|
-
review: this.#store.grantReviews().filter(({ subject }) => only === void 0 || subject === only).map(({ subject, levels, at }) => ({
|
|
27327
|
+
grants: this.#all().filter(({ subject }) => !isRelationKey(subject)).filter(({ subject }) => only === void 0 || subject === only).map(({ grant }) => this.#view(grant)).sort((a, b) => b.ts - a.ts || (a.id < b.id ? 1 : -1)),
|
|
27328
|
+
review: this.#store.grantReviews().filter(({ subject }) => !isRelationKey(subject)).filter(({ subject }) => only === void 0 || subject === only).map(({ subject, levels, at }) => ({
|
|
26756
27329
|
subject: this.#subjectView(subject),
|
|
26757
27330
|
...levels,
|
|
26758
27331
|
at
|
|
@@ -26792,6 +27365,30 @@ var init_grants = __esmMin((() => {
|
|
|
26792
27365
|
...levels
|
|
26793
27366
|
}, opts);
|
|
26794
27367
|
}
|
|
27368
|
+
setRelations(changes) {
|
|
27369
|
+
if (changes.length === 0) return;
|
|
27370
|
+
const { identity, realm, me } = this.#host.joined();
|
|
27371
|
+
const now = this.#host.now();
|
|
27372
|
+
const grants = changes.map(({ subject, levels }) => signConsentGrant(identity, {
|
|
27373
|
+
realm: realm.realm,
|
|
27374
|
+
person: me.person,
|
|
27375
|
+
subject,
|
|
27376
|
+
levels,
|
|
27377
|
+
now
|
|
27378
|
+
}));
|
|
27379
|
+
this.#host.tx(() => {
|
|
27380
|
+
for (const grant of grants) {
|
|
27381
|
+
const key = grantSubjectKey(grant.subject);
|
|
27382
|
+
this.#store.putGrant(key, grant);
|
|
27383
|
+
this.#store.deleteGrantReview(key);
|
|
27384
|
+
}
|
|
27385
|
+
this.#sync("grant", grants);
|
|
27386
|
+
});
|
|
27387
|
+
this.#host.log("grant.set", {
|
|
27388
|
+
subject: "relation",
|
|
27389
|
+
grants: grants.length
|
|
27390
|
+
});
|
|
27391
|
+
}
|
|
26795
27392
|
check(p) {
|
|
26796
27393
|
const { identity, realm, me } = this.#host.joined();
|
|
26797
27394
|
const now = this.#host.now();
|
|
@@ -26835,7 +27432,7 @@ var init_grants = __esmMin((() => {
|
|
|
26835
27432
|
}
|
|
26836
27433
|
const key = grantSubjectKey(grant.subject);
|
|
26837
27434
|
const held = this.#held(key);
|
|
26838
|
-
if (!held && this.#store.grantCount() >= LIMITS.grantsPerPerson) {
|
|
27435
|
+
if (!held && !isRelationKey(key) && this.#store.grantCount() >= LIMITS.grantsPerPerson) {
|
|
26839
27436
|
this.#host.log("grant.sync.skipped", {
|
|
26840
27437
|
id: env.id,
|
|
26841
27438
|
code: "rate_limited"
|
|
@@ -26976,10 +27573,14 @@ var init_grants = __esmMin((() => {
|
|
|
26976
27573
|
return grantSubjectKey(target);
|
|
26977
27574
|
}
|
|
26978
27575
|
#subjectOf(key) {
|
|
26979
|
-
|
|
27576
|
+
if (key.startsWith("person:")) return { person: key.slice(7) };
|
|
27577
|
+
if (isRelationKey(key)) return { relation: key.slice(9) };
|
|
27578
|
+
return { conv: key.slice(5) };
|
|
26980
27579
|
}
|
|
26981
27580
|
#subjectView(key) {
|
|
26982
|
-
|
|
27581
|
+
const subject = this.#subjectOf(key);
|
|
27582
|
+
if ("relation" in subject) throw new MessagingError("internal", "a relation grant has no grant view");
|
|
27583
|
+
return subject;
|
|
26983
27584
|
}
|
|
26984
27585
|
#view(grant) {
|
|
26985
27586
|
return {
|
|
@@ -27140,7 +27741,7 @@ var init_cards = __esmMin((() => {
|
|
|
27140
27741
|
seq,
|
|
27141
27742
|
now,
|
|
27142
27743
|
...grant !== void 0 && typeof held?.id === "string" ? { grantId: held.id } : {},
|
|
27143
|
-
can: cardCan(relation, grant, now)
|
|
27744
|
+
can: cardCan(relation, grant, now, this.#host.reach?.() ?? {})
|
|
27144
27745
|
});
|
|
27145
27746
|
for (const device of realm.known(person).devices) this.#host.route(this.#host.seal(device.machine, cardMessage({ card }, "card")));
|
|
27146
27747
|
this.#host.log("card.sent", { seq });
|
|
@@ -27270,7 +27871,8 @@ var init_conversation_requests = __esmMin((() => {
|
|
|
27270
27871
|
return this.#ids().map((id) => this.get(id)).sort((a, b) => a.at - b.at || a.id.localeCompare(b.id));
|
|
27271
27872
|
}
|
|
27272
27873
|
waitingOnThem() {
|
|
27273
|
-
|
|
27874
|
+
const now = this.host.now(), rows = this.list().filter((r) => r.direction === "outgoing");
|
|
27875
|
+
const submitted = rows.filter((r) => r.state === "submitted" && r.request.descriptor.expiresAt > now).map((r) => ({
|
|
27274
27876
|
id: r.id,
|
|
27275
27877
|
kind: "contact",
|
|
27276
27878
|
to: r.person,
|
|
@@ -27278,6 +27880,16 @@ var init_conversation_requests = __esmMin((() => {
|
|
|
27278
27880
|
at: r.at,
|
|
27279
27881
|
cid: r.request.descriptor.cid
|
|
27280
27882
|
}));
|
|
27883
|
+
const resend = rows.filter((r) => r.state === "resend" && r.at + LIMITS.ttlMs > now && !rows.some((n) => n.person === r.person && n.request && n.at >= r.at)).map((r) => ({
|
|
27884
|
+
id: r.id,
|
|
27885
|
+
kind: "contact",
|
|
27886
|
+
to: r.person,
|
|
27887
|
+
name: r.person,
|
|
27888
|
+
at: r.at,
|
|
27889
|
+
cid: dmConvId(this.host.person, r.person),
|
|
27890
|
+
resend: true
|
|
27891
|
+
}));
|
|
27892
|
+
return [...submitted, ...resend];
|
|
27281
27893
|
}
|
|
27282
27894
|
cutoverLegacy(outgoing = []) {
|
|
27283
27895
|
this.host.store.tx(() => {
|
|
@@ -27359,6 +27971,7 @@ var init_conversation_requests = __esmMin((() => {
|
|
|
27359
27971
|
if (d.realm !== this.host.realm || d.to !== this.host.person) throw new MessagingError("invalid_request", "request is for another recipient");
|
|
27360
27972
|
if (d.issuedAt > this.host.now() + LIMITS.clockSkewMs || d.expiresAt <= this.host.now()) throw new MessagingError("expired", "request has expired");
|
|
27361
27973
|
if (this.host.chat(d.from) === "blocked") throw new MessagingError("declined", "request declined");
|
|
27974
|
+
if (this.host.refuses?.(d.from)) throw new MessagingError("refused", "this person accepts no message requests from outside their org");
|
|
27362
27975
|
return this.host.store.tx(() => {
|
|
27363
27976
|
const old = this.get(d.id);
|
|
27364
27977
|
if (old) {
|
|
@@ -27565,6 +28178,7 @@ var init_requests = __esmMin((() => {
|
|
|
27565
28178
|
resolve: (email) => this.#resolve(email),
|
|
27566
28179
|
current: (person) => h.current?.([person]) ?? Promise.resolve(),
|
|
27567
28180
|
chat: (person) => h.grants.personGrant(person)?.chat,
|
|
28181
|
+
refuses: (person) => h.grants.decide(person, { kind: "request" }).action === "refuse",
|
|
27568
28182
|
grantChat: (person, chat) => {
|
|
27569
28183
|
h.grants.setPerson(person, { chat }, { card: false });
|
|
27570
28184
|
},
|
|
@@ -27628,7 +28242,7 @@ var init_requests = __esmMin((() => {
|
|
|
27628
28242
|
}, proof, body);
|
|
27629
28243
|
}
|
|
27630
28244
|
});
|
|
27631
|
-
this.#lifecycle.cutoverLegacy();
|
|
28245
|
+
this.#lifecycle.cutoverLegacy(h.store.legacyOutgoingRequests(h.now()));
|
|
27632
28246
|
return this.#lifecycle;
|
|
27633
28247
|
}
|
|
27634
28248
|
#mailbox() {
|
|
@@ -27714,12 +28328,16 @@ var init_requests = __esmMin((() => {
|
|
|
27714
28328
|
const sent = parseWire(value);
|
|
27715
28329
|
if (machine !== sent.device) return true;
|
|
27716
28330
|
if (payload.stage === "held") this.host.store.setKv(`conv.request.held.${sent.request}`, "true");
|
|
28331
|
+
if (payload.stage === "delivered" || payload.stage === "read") {
|
|
28332
|
+
if (!this.host.store.getKv(`conv.request.outdated.${sent.request}`)) this.host.log("request.outdated", { id: sent.request });
|
|
28333
|
+
this.host.store.setKv(`conv.request.outdated.${sent.request}`, "true");
|
|
28334
|
+
}
|
|
27717
28335
|
return true;
|
|
27718
28336
|
}
|
|
27719
28337
|
async waitingOnThem() {
|
|
27720
|
-
return this.#current().waitingOnThem().map((row) => ({
|
|
28338
|
+
return this.#current().waitingOnThem().map(({ resend, ...row }) => ({
|
|
27721
28339
|
...row,
|
|
27722
|
-
state: this.host.store.getKv(`conv.request.held.${row.id}`) === "true" ? "held" : "pending-delivery"
|
|
28340
|
+
state: resend ? "resend" : this.host.store.getKv(`conv.request.outdated.${row.id}`) === "true" ? "outdated" : this.host.store.getKv(`conv.request.held.${row.id}`) === "true" ? "held" : "pending-delivery"
|
|
27723
28341
|
}));
|
|
27724
28342
|
}
|
|
27725
28343
|
get(id) {
|
|
@@ -27829,6 +28447,92 @@ var init_requests = __esmMin((() => {
|
|
|
27829
28447
|
}
|
|
27830
28448
|
};
|
|
27831
28449
|
}));
|
|
28450
|
+
// packages/daemon/dist/consent/reach.js
|
|
28451
|
+
function revision(grants, choices) {
|
|
28452
|
+
return sha256(canonicalize({
|
|
28453
|
+
records: Object.fromEntries(GROUPS.map((group) => [group, grants.relationRecord(RELATION[group])])),
|
|
28454
|
+
choices
|
|
28455
|
+
})).slice(0, 32);
|
|
28456
|
+
}
|
|
28457
|
+
function reachSnapshot(grants) {
|
|
28458
|
+
const choices = grants.reach();
|
|
28459
|
+
const lapsed = reachChoices(grants.relationReview("outside"), grants.relationReview("org"));
|
|
28460
|
+
return {
|
|
28461
|
+
revision: revision(grants, choices),
|
|
28462
|
+
available: true,
|
|
28463
|
+
groups: REACH_QUESTIONS.map((question) => ({
|
|
28464
|
+
id: question.id,
|
|
28465
|
+
label: question.label,
|
|
28466
|
+
options: question.options.map((option) => ({ ...option })),
|
|
28467
|
+
value: choices[question.id] ?? null,
|
|
28468
|
+
...lapsed[question.id] !== void 0 ? { lapsed: lapsed[question.id] } : {}
|
|
28469
|
+
}))
|
|
28470
|
+
};
|
|
28471
|
+
}
|
|
28472
|
+
function changesOf(grants, p) {
|
|
28473
|
+
if (p.revision !== revision(grants, grants.reach())) throw new MessagingError("conflict", "your reach choices changed since they were read; read them again and choose again");
|
|
28474
|
+
return GROUPS.flatMap((group) => p.changes[group] === void 0 ? [] : [[group, p.changes[group]]]);
|
|
28475
|
+
}
|
|
28476
|
+
function reachSet(grants, p) {
|
|
28477
|
+
const changes = changesOf(grants, p);
|
|
28478
|
+
grants.setRelations(changes.map(([group, value]) => {
|
|
28479
|
+
const { levels } = reachGrant(group, value);
|
|
28480
|
+
return {
|
|
28481
|
+
subject: { relation: RELATION[group] },
|
|
28482
|
+
levels
|
|
28483
|
+
};
|
|
28484
|
+
}));
|
|
28485
|
+
return reachSnapshot(grants);
|
|
28486
|
+
}
|
|
28487
|
+
function reachPreview(grants, p) {
|
|
28488
|
+
const changes = changesOf(grants, p);
|
|
28489
|
+
if (changes.length === 0) return "Nothing changes.";
|
|
28490
|
+
return changes.map(([group, value]) => SENTENCES[group][value]).join(" ");
|
|
28491
|
+
}
|
|
28492
|
+
var RELATION, GROUPS, SENTENCES;
|
|
28493
|
+
var init_reach = __esmMin((() => {
|
|
28494
|
+
init_dist$3();
|
|
28495
|
+
RELATION = {
|
|
28496
|
+
message: "outside",
|
|
28497
|
+
ask: "org"
|
|
28498
|
+
};
|
|
28499
|
+
GROUPS = ["message", "ask"];
|
|
28500
|
+
SENTENCES = {
|
|
28501
|
+
message: {
|
|
28502
|
+
open: "Anyone outside your org may message you.",
|
|
28503
|
+
ask: "People outside your org send you a message request first.",
|
|
28504
|
+
never: "No one outside your org may message you or send you a request, except people you have let message you."
|
|
28505
|
+
},
|
|
28506
|
+
ask: {
|
|
28507
|
+
open: "Your teammates' agents may ask yours without asking you; their requests run guarded.",
|
|
28508
|
+
ask: "You answer each request from a teammate's agent to yours first.",
|
|
28509
|
+
never: "Your teammates' agents may not ask yours."
|
|
28510
|
+
}
|
|
28511
|
+
};
|
|
28512
|
+
}));
|
|
28513
|
+
// packages/daemon/dist/conv-caps.js
|
|
28514
|
+
async function ensureCurrent(link, own, persons, handle) {
|
|
28515
|
+
const others = [...new Set(persons)].filter((p) => p !== own);
|
|
28516
|
+
if (!others.length) return;
|
|
28517
|
+
let outdated;
|
|
28518
|
+
try {
|
|
28519
|
+
outdated = (await link?.convCaps?.(others))?.outdated ?? [];
|
|
28520
|
+
} catch {
|
|
28521
|
+
return;
|
|
28522
|
+
}
|
|
28523
|
+
if (!outdated.length) return;
|
|
28524
|
+
const handles = await Promise.all(outdated.map(async (p) => {
|
|
28525
|
+
try {
|
|
28526
|
+
return await handle(p);
|
|
28527
|
+
} catch {
|
|
28528
|
+
return p;
|
|
28529
|
+
}
|
|
28530
|
+
}));
|
|
28531
|
+
throw new MessagingError("peer_outdated", `${handles.join(", ")} ${handles.length === 1 ? "needs" : "need"} to update Messaging`);
|
|
28532
|
+
}
|
|
28533
|
+
var init_conv_caps = __esmMin((() => {
|
|
28534
|
+
init_dist$3();
|
|
28535
|
+
}));
|
|
27832
28536
|
// packages/daemon/dist/consent/sentence.js
|
|
27833
28537
|
function grantSentence(p, me, now) {
|
|
27834
28538
|
const levels = levelsFrom(p, now);
|
|
@@ -27857,6 +28561,38 @@ function grantSentence(p, me, now) {
|
|
|
27857
28561
|
var init_sentence = __esmMin((() => {
|
|
27858
28562
|
init_grants();
|
|
27859
28563
|
}));
|
|
28564
|
+
// packages/daemon/dist/wake-dms.js
|
|
28565
|
+
function teammateDms(conversations, self) {
|
|
28566
|
+
const member = (state, person) => state.participants.some((p) => p.person === person && p.state === "member");
|
|
28567
|
+
const seated = (state, person) => state.participants.some((p) => p.p === person && p.state === "member");
|
|
28568
|
+
const channels = conversations.flatMap((c) => c.state?.kind === "channel" && seated(c.state, self) ? [c.state] : []);
|
|
28569
|
+
const shares = new Map();
|
|
28570
|
+
const shared = (person) => {
|
|
28571
|
+
let found = shares.get(person);
|
|
28572
|
+
if (found === void 0) shares.set(person, found = channels.some((state) => seated(state, person)));
|
|
28573
|
+
return found;
|
|
28574
|
+
};
|
|
28575
|
+
const found = [];
|
|
28576
|
+
for (const { cid, state } of conversations) {
|
|
28577
|
+
if (state?.kind !== "dm" || !member(state, self)) continue;
|
|
28578
|
+
const others = [...new Set(state.participants.filter((p) => p.person !== self).map((p) => p.person))];
|
|
28579
|
+
if (others.length !== 1) continue;
|
|
28580
|
+
const person = others[0];
|
|
28581
|
+
if (!member(state, person) || !shared(person)) continue;
|
|
28582
|
+
found.push({
|
|
28583
|
+
cid,
|
|
28584
|
+
person
|
|
28585
|
+
});
|
|
28586
|
+
}
|
|
28587
|
+
return found;
|
|
28588
|
+
}
|
|
28589
|
+
function wakeArmable(grants, person, org) {
|
|
28590
|
+
const chat = grants.personGrant(person)?.chat;
|
|
28591
|
+
if (chat === "blocked" || chat === "muted") return false;
|
|
28592
|
+
if (grants.hides(person, org)) return false;
|
|
28593
|
+
return true;
|
|
28594
|
+
}
|
|
28595
|
+
var init_wake_dms = __esmMin((() => {}));
|
|
27860
28596
|
// packages/daemon/dist/daemon.js
|
|
27861
28597
|
async function startDaemon$1(options) {
|
|
27862
28598
|
const daemon = await Daemon.start(options);
|
|
@@ -27868,6 +28604,7 @@ async function startDaemon$1(options) {
|
|
|
27868
28604
|
status: () => daemon.status(),
|
|
27869
28605
|
conversations: () => daemon.conversations(),
|
|
27870
28606
|
conversationsReady: () => daemon.conversationsReady(),
|
|
28607
|
+
actionTokens: () => daemon.actionTokens(),
|
|
27871
28608
|
sweep: () => daemon.sweep(),
|
|
27872
28609
|
close: () => daemon.close()
|
|
27873
28610
|
};
|
|
@@ -27875,6 +28612,16 @@ async function startDaemon$1(options) {
|
|
|
27875
28612
|
function jsonBytes(value) {
|
|
27876
28613
|
return Buffer.byteLength(JSON.stringify(value) ?? "");
|
|
27877
28614
|
}
|
|
28615
|
+
function signInMessage(message, tool) {
|
|
28616
|
+
return {
|
|
28617
|
+
...message,
|
|
28618
|
+
metadata: {
|
|
28619
|
+
...message.metadata,
|
|
28620
|
+
[URI.signIn]: { tool }
|
|
28621
|
+
},
|
|
28622
|
+
extensions: [...message.extensions ?? [], URI.signIn]
|
|
28623
|
+
};
|
|
28624
|
+
}
|
|
27878
28625
|
function boundedRecord(record, limit) {
|
|
27879
28626
|
if (jsonBytes(record) <= limit) return structuredClone(record);
|
|
27880
28627
|
const { history: _history, artifacts: _artifacts, ...task } = record.task;
|
|
@@ -27982,7 +28729,7 @@ function signInToken(token) {
|
|
|
27982
28729
|
return false;
|
|
27983
28730
|
}
|
|
27984
28731
|
}
|
|
27985
|
-
var DAY, KEYCHAIN_LEFTOVERS_KEY, DEFAULT_TUNING, KEPT_MS, INPUT_TIMEOUT_MS, TASK_BYTES, PREDECESSOR_KEY, REPLACE_LABEL_KEY, REPLACED_KEY, ERASURES_PER_DAY, DEVICE_NOTICES_KEY, TRUST_NOTICE_MS, DEVICES_CHANGED_MS, MACHINE_KEY, DEFAULT_INVITE_TTL_MS, Daemon, LIST_BYTES;
|
|
28732
|
+
var DAY, KEYCHAIN_LEFTOVERS_KEY, DEFAULT_TUNING, KEPT_MS, INPUT_TIMEOUT_MS, TASK_BYTES, PREDECESSOR_KEY, REPLACE_LABEL_KEY, REPLACED_KEY, ERASURES_PER_DAY, DEVICE_NOTICES_KEY, TRUST_NOTICE_MS, DEVICES_CHANGED_MS, MACHINE_KEY, DEFAULT_INVITE_TTL_MS, Daemon, LIST_BYTES, NAMED_PERSONS;
|
|
27986
28733
|
var init_daemon = __esmMin((() => {
|
|
27987
28734
|
init_dist$3();
|
|
27988
28735
|
init_dist$2();
|
|
@@ -28012,6 +28759,7 @@ var init_daemon = __esmMin((() => {
|
|
|
28012
28759
|
init_answer_preview();
|
|
28013
28760
|
init_snapshot();
|
|
28014
28761
|
init_notices();
|
|
28762
|
+
init_task_view();
|
|
28015
28763
|
init_counterpart();
|
|
28016
28764
|
init_resolve();
|
|
28017
28765
|
init_secrets();
|
|
@@ -28021,11 +28769,15 @@ var init_daemon = __esmMin((() => {
|
|
|
28021
28769
|
init_tasks();
|
|
28022
28770
|
init_version();
|
|
28023
28771
|
init_wake_bridge();
|
|
28772
|
+
init_action_tokens();
|
|
28024
28773
|
init_grants();
|
|
28025
28774
|
init_holds();
|
|
28026
28775
|
init_cards();
|
|
28027
28776
|
init_requests();
|
|
28777
|
+
init_reach();
|
|
28778
|
+
init_conv_caps();
|
|
28028
28779
|
init_sentence();
|
|
28780
|
+
init_wake_dms();
|
|
28029
28781
|
DAY = 864e5;
|
|
28030
28782
|
KEYCHAIN_LEFTOVERS_KEY = "keychain.stale";
|
|
28031
28783
|
DEFAULT_TUNING = {
|
|
@@ -28108,11 +28860,14 @@ var init_daemon = __esmMin((() => {
|
|
|
28108
28860
|
#cards;
|
|
28109
28861
|
#requests;
|
|
28110
28862
|
#notices;
|
|
28863
|
+
#named = new Map();
|
|
28864
|
+
#questions = new Map();
|
|
28111
28865
|
#jellyHost;
|
|
28112
28866
|
#attached = false;
|
|
28113
28867
|
#wakeArmed = false;
|
|
28114
28868
|
#snapshots;
|
|
28115
28869
|
#jellyAuth;
|
|
28870
|
+
#actions;
|
|
28116
28871
|
#state = "starting";
|
|
28117
28872
|
#sync;
|
|
28118
28873
|
#pending = [];
|
|
@@ -28151,6 +28906,7 @@ var init_daemon = __esmMin((() => {
|
|
|
28151
28906
|
this.#jellyHttp = options.jellyHttp;
|
|
28152
28907
|
this.#loginWait = options.loginWait;
|
|
28153
28908
|
this.#jellyHost = options.jellyHost;
|
|
28909
|
+
this.#actions = new ActionTokens(() => this.#now());
|
|
28154
28910
|
this.#config = readConfig(paths.config);
|
|
28155
28911
|
this.#configStamp = configStamp(paths.config);
|
|
28156
28912
|
this.closed = new Promise((resolve) => this.#settleClosed = resolve);
|
|
@@ -28177,9 +28933,10 @@ var init_daemon = __esmMin((() => {
|
|
|
28177
28933
|
put: (key, value) => store.setKv(key, value),
|
|
28178
28934
|
fresh: (people) => this.#withFresh(people, () => {}),
|
|
28179
28935
|
refuseSecrets: (value) => this.#refuseSecrets(value, "conv.send", "conversation line"),
|
|
28180
|
-
blocked: (
|
|
28936
|
+
blocked: (participant, org) => this.#grants.hides(participant, org),
|
|
28181
28937
|
current: (persons) => this.#ensureCurrent(persons),
|
|
28182
|
-
outgoingRequests: () => this.#requests.waitingOnThem()
|
|
28938
|
+
outgoingRequests: () => this.#requests.waitingOnThem(),
|
|
28939
|
+
task: (id, role, ctx, authority) => this.#personTaskEntry(id, role, ctx, authority)
|
|
28183
28940
|
});
|
|
28184
28941
|
this.#conversationInbox = new ConversationInbox({
|
|
28185
28942
|
engine: () => this.#conversationEngine(),
|
|
@@ -28283,6 +29040,7 @@ var init_daemon = __esmMin((() => {
|
|
|
28283
29040
|
joined: () => this.#joined(),
|
|
28284
29041
|
relation: (person) => this.#grants.relation(person),
|
|
28285
29042
|
personGrant: (person) => this.#grants.personGrant(person),
|
|
29043
|
+
reach: () => this.#grants.reach(),
|
|
28286
29044
|
prefetch: (person) => this.#grants.prefetch(person),
|
|
28287
29045
|
fresh: async (persons, fn) => {
|
|
28288
29046
|
await this.#withFresh(persons, () => this.#tx(fn), { first: false });
|
|
@@ -28656,10 +29414,10 @@ var init_daemon = __esmMin((() => {
|
|
|
28656
29414
|
} : p);
|
|
28657
29415
|
},
|
|
28658
29416
|
"device.list": () => {
|
|
28659
|
-
return { devices: (this.#directory?.list() ?? this.#rosterDevices()).devices.map((d) => d.self && this.#away() ? {
|
|
29417
|
+
return { devices: (this.#directory?.list() ?? this.#rosterDevices()).devices.map((d) => this.#withFeatures(d.self && this.#away() ? {
|
|
28660
29418
|
...d,
|
|
28661
29419
|
away: true
|
|
28662
|
-
} : d) };
|
|
29420
|
+
} : d)) };
|
|
28663
29421
|
},
|
|
28664
29422
|
"device.remove": (p) => this.#homeDirectory("device.remove").remove(p),
|
|
28665
29423
|
"device.link": (p) => this.#homeDirectory("device.link").link(p),
|
|
@@ -28719,10 +29477,13 @@ var init_daemon = __esmMin((() => {
|
|
|
28719
29477
|
...this.#bound(p, ctx),
|
|
28720
29478
|
kind: "message"
|
|
28721
29479
|
}),
|
|
28722
|
-
"task.list": (p, ctx) => this.#listTasks(this.#bound(p, ctx)),
|
|
28723
|
-
"task.get": (p, ctx) => this.#getTask(this.#bound(p, ctx)),
|
|
28724
|
-
"task.update": (p, ctx) => this.#updateTask(this.#bound(p, ctx)),
|
|
28725
|
-
"task.cancel": (p, ctx) => this.#cancelTask(this.#bound(
|
|
29480
|
+
"task.list": (p, ctx) => this.#listTasks(this.#bound(p, ctx), ctx.tier === "admin"),
|
|
29481
|
+
"task.get": (p, ctx) => this.#getTask(this.#bound(p, ctx), ctx.tier === "admin"),
|
|
29482
|
+
"task.update": (p, ctx) => this.#updateTask(this.#bound(p, ctx), ctx.tier === "admin"),
|
|
29483
|
+
"task.cancel": (p, ctx, authority) => p.token === void 0 ? this.#cancelTask(this.#bound({
|
|
29484
|
+
...p,
|
|
29485
|
+
key: p.key
|
|
29486
|
+
}, ctx), ctx.tier === "admin") : this.#cancelByToken(p, p.token, this.#tokenView("task.cancel", ctx, authority)),
|
|
28726
29487
|
"events.subscribe": (p, ctx) => {
|
|
28727
29488
|
for (const key of p.keys) this.#bound({ key }, ctx);
|
|
28728
29489
|
return { ok: true };
|
|
@@ -28751,13 +29512,28 @@ var init_daemon = __esmMin((() => {
|
|
|
28751
29512
|
this.#grants.check(p);
|
|
28752
29513
|
return { sentence: grantSentence(p, this.#joined().me.person, this.#now()) };
|
|
28753
29514
|
},
|
|
28754
|
-
"
|
|
28755
|
-
|
|
28756
|
-
|
|
28757
|
-
|
|
28758
|
-
|
|
28759
|
-
|
|
28760
|
-
|
|
29515
|
+
"reach.get": () => reachSnapshot(this.#grants),
|
|
29516
|
+
"reach.set": (p) => reachSet(this.#grants, p),
|
|
29517
|
+
"reach.set.preview": (p) => ({ sentence: reachPreview(this.#grants, p) }),
|
|
29518
|
+
"request.list": async (_p, ctx, authority) => {
|
|
29519
|
+
const requests = [
|
|
29520
|
+
...this.#holds.list().requests,
|
|
29521
|
+
...await this.#requests.list(),
|
|
29522
|
+
...this.#conversationInvitations.list()
|
|
29523
|
+
];
|
|
29524
|
+
const view = actionView(ctx, authority, void 0);
|
|
29525
|
+
return { requests: view === void 0 ? requests : requests.map((request) => this.#withActions(request, view)) };
|
|
29526
|
+
},
|
|
29527
|
+
"request.answer": (p, ctx, authority) => {
|
|
29528
|
+
this.#requestToken("request.answer", p, ctx, authority, "redeem");
|
|
29529
|
+
const { token: _token, ...answer } = p;
|
|
29530
|
+
return this.#conversationInvitations.holds(answer.id) ? this.#conversationInvitations.answer(answer.id, answer.answer, answer.all) : this.#requests.holds(answer.id) ? this.#requests.answer(answer) : this.#holds.answer(answer);
|
|
29531
|
+
},
|
|
29532
|
+
"request.answer.preview": (p, ctx, authority) => {
|
|
29533
|
+
this.#requestToken("request.answer.preview", p, ctx, authority, "check");
|
|
29534
|
+
const { token: _token, ...answer } = p;
|
|
29535
|
+
return this.#answerPreview(answer);
|
|
29536
|
+
},
|
|
28761
29537
|
"contact.request": (p) => this.#requests.request(p),
|
|
28762
29538
|
"contact.request.preview": (p) => this.#requests.preview(p),
|
|
28763
29539
|
"card.get": async (p) => {
|
|
@@ -28774,6 +29550,9 @@ var init_daemon = __esmMin((() => {
|
|
|
28774
29550
|
"notice.subscribe": (p, ctx, authority) => this.#notices.subscribe(ctx, p, authority?.scope === "host" ? authority.expiresAt : void 0),
|
|
28775
29551
|
"notice.list": (p) => this.#notices.list(p),
|
|
28776
29552
|
"notice.ack": (p) => this.#notices.ack(p),
|
|
29553
|
+
"task.question": (p, ctx) => this.#setQuestion(this.#bound(p, ctx)),
|
|
29554
|
+
"tasks.list": (p, ctx, authority) => this.#personTasks(p, actionView(ctx, authority, void 0)),
|
|
29555
|
+
"tasks.get": (p, ctx, authority) => this.#personTaskGet(p, actionView(ctx, authority, void 0)),
|
|
28777
29556
|
"device.remove.preview": (p) => this.#removePreview(p),
|
|
28778
29557
|
...this.#conversationIpc.handlers()
|
|
28779
29558
|
};
|
|
@@ -28840,7 +29619,7 @@ var init_daemon = __esmMin((() => {
|
|
|
28840
29619
|
else this.#publish(event);
|
|
28841
29620
|
}
|
|
28842
29621
|
#emitTask(row, origin, update) {
|
|
28843
|
-
const record = this.#withFollowUps(boundedRecord(row.record, TASK_BYTES));
|
|
29622
|
+
const record = this.#taskView(this.#withFollowUps(boundedRecord(row.record, TASK_BYTES)));
|
|
28844
29623
|
this.#emit({
|
|
28845
29624
|
type: "task",
|
|
28846
29625
|
key: row.record.key,
|
|
@@ -28848,6 +29627,10 @@ var init_daemon = __esmMin((() => {
|
|
|
28848
29627
|
origin,
|
|
28849
29628
|
...update ? { update: structuredClone(update) } : {}
|
|
28850
29629
|
});
|
|
29630
|
+
this.#conversationIpc.taskChanged({
|
|
29631
|
+
id: row.record.task.id,
|
|
29632
|
+
role: row.record.role
|
|
29633
|
+
});
|
|
28851
29634
|
}
|
|
28852
29635
|
#overBudget(before, after) {
|
|
28853
29636
|
const size = jsonBytes(after);
|
|
@@ -29049,6 +29832,7 @@ var init_daemon = __esmMin((() => {
|
|
|
29049
29832
|
}
|
|
29050
29833
|
#disconnected(ctx) {
|
|
29051
29834
|
if (this.#closed) return;
|
|
29835
|
+
this.#actions.disconnected(ctx.id);
|
|
29052
29836
|
this.#notices.disconnected(ctx.id);
|
|
29053
29837
|
let changed = false;
|
|
29054
29838
|
for (const [key, lapsed] of [...this.#lapsed]) if (lapsed.delete(ctx.id) && lapsed.size === 0) this.#lapsed.delete(key);
|
|
@@ -30042,6 +30826,11 @@ var init_daemon = __esmMin((() => {
|
|
|
30042
30826
|
};
|
|
30043
30827
|
this.#store.putTask(row);
|
|
30044
30828
|
this.#emitTask(row, "peer");
|
|
30829
|
+
if (sender.person !== this.#joined().me.person) this.#notices.task({
|
|
30830
|
+
taskId,
|
|
30831
|
+
person: sender.person,
|
|
30832
|
+
at: now
|
|
30833
|
+
});
|
|
30045
30834
|
} else if (executor) {
|
|
30046
30835
|
executor.record.task.history = [...executor.record.task.history ?? [], message];
|
|
30047
30836
|
executor.record.updatedAt = now;
|
|
@@ -30129,6 +30918,7 @@ var init_daemon = __esmMin((() => {
|
|
|
30129
30918
|
state: "TASK_STATE_CANCELED",
|
|
30130
30919
|
timestamp: iso(now)
|
|
30131
30920
|
};
|
|
30921
|
+
this.#questions.delete(row.record.task.id);
|
|
30132
30922
|
row.record.task.status = status;
|
|
30133
30923
|
row.record.updatedAt = now;
|
|
30134
30924
|
this.#store.putTask(row);
|
|
@@ -30198,10 +30988,10 @@ var init_daemon = __esmMin((() => {
|
|
|
30198
30988
|
if (other && other.record.key === key) throw new MessagingError("invalid_state", role === "executor" ? "only the executor session may update this task" : "only the requester session may cancel this task");
|
|
30199
30989
|
throw new MessagingError("not_found", "no such task for this session");
|
|
30200
30990
|
}
|
|
30201
|
-
#getTask(p) {
|
|
30991
|
+
async #getTask(p, owner) {
|
|
30202
30992
|
for (const role of ["requester", "executor"]) {
|
|
30203
30993
|
const row = this.#store.task(p.taskId, role);
|
|
30204
|
-
if (row && row.record.key === p.key) return this.#withFollowUps(row.record);
|
|
30994
|
+
if (row && row.record.key === p.key) return this.#withQuestion(await this.#viewNamed(this.#withFollowUps(row.record)), owner);
|
|
30205
30995
|
}
|
|
30206
30996
|
throw new MessagingError("not_found", "no such task for this session");
|
|
30207
30997
|
}
|
|
@@ -30221,7 +31011,7 @@ var init_daemon = __esmMin((() => {
|
|
|
30221
31011
|
followUps
|
|
30222
31012
|
};
|
|
30223
31013
|
}
|
|
30224
|
-
#listTasks(p) {
|
|
31014
|
+
async #listTasks(p, owner) {
|
|
30225
31015
|
const limit = p.limit ?? 50;
|
|
30226
31016
|
const { rows, total, more } = this.#store.listTasks({
|
|
30227
31017
|
key: p.key,
|
|
@@ -30244,8 +31034,9 @@ var init_daemon = __esmMin((() => {
|
|
|
30244
31034
|
}
|
|
30245
31035
|
const last = tasks.at(-1);
|
|
30246
31036
|
const truncated = tasks.length < rows.length;
|
|
31037
|
+
await Promise.all([...new Set(tasks.map((t) => t.peer.person))].map((person) => this.#nameOf(person)));
|
|
30247
31038
|
return {
|
|
30248
|
-
tasks,
|
|
31039
|
+
tasks: tasks.map((t) => this.#withQuestion(this.#taskView(t), owner)),
|
|
30249
31040
|
total,
|
|
30250
31041
|
...(more || truncated) && last ? { nextCursor: encodeCursor({
|
|
30251
31042
|
updatedAt: last.updatedAt,
|
|
@@ -30254,7 +31045,7 @@ var init_daemon = __esmMin((() => {
|
|
|
30254
31045
|
}) } : {}
|
|
30255
31046
|
};
|
|
30256
31047
|
}
|
|
30257
|
-
async #updateTask(p) {
|
|
31048
|
+
async #updateTask(p, owner) {
|
|
30258
31049
|
this.#joined();
|
|
30259
31050
|
const row = this.#ownTask(p.key, p.taskId, "executor");
|
|
30260
31051
|
this.#refuseSecrets(p, "task.update", "task update");
|
|
@@ -30266,7 +31057,7 @@ var init_daemon = __esmMin((() => {
|
|
|
30266
31057
|
const now = this.#now();
|
|
30267
31058
|
const status = statusChange ? {
|
|
30268
31059
|
state: p.state,
|
|
30269
|
-
...p.message !== void 0 ? { message: agentMessage(p.message.parts, task.id, task.contextId, now) } : {},
|
|
31060
|
+
...p.signIn !== void 0 ? { message: signInMessage(agentMessage(p.message?.parts ?? [{ text: "Sign-in required." }], task.id, task.contextId, now), p.signIn.tool) } : p.message !== void 0 ? { message: agentMessage(p.message.parts, task.id, task.contextId, now) } : {},
|
|
30270
31061
|
timestamp: iso(now)
|
|
30271
31062
|
} : void 0;
|
|
30272
31063
|
const after = structuredClone(row.record);
|
|
@@ -30305,6 +31096,7 @@ var init_daemon = __esmMin((() => {
|
|
|
30305
31096
|
contextId,
|
|
30306
31097
|
status
|
|
30307
31098
|
}, { replyTo: request });
|
|
31099
|
+
this.#questions.delete(task.id);
|
|
30308
31100
|
task.status = status;
|
|
30309
31101
|
row.record.updatedAt = now;
|
|
30310
31102
|
this.#emitTask(row, "local", { status });
|
|
@@ -30314,12 +31106,94 @@ var init_daemon = __esmMin((() => {
|
|
|
30314
31106
|
this.#store.putTask(row);
|
|
30315
31107
|
});
|
|
30316
31108
|
await this.#settle(ids);
|
|
30317
|
-
return boundedRecord(this.#store.task(p.taskId, "executor")?.record ?? row.record, TASK_BYTES);
|
|
31109
|
+
return this.#withQuestion(await this.#viewNamed(boundedRecord(this.#store.task(p.taskId, "executor")?.record ?? row.record, TASK_BYTES)), owner);
|
|
31110
|
+
}
|
|
31111
|
+
async #cancelTask(p, owner) {
|
|
31112
|
+
this.#joined();
|
|
31113
|
+
return this.#cancelRow(this.#ownTask(p.key, p.taskId, "requester"), p, owner);
|
|
31114
|
+
}
|
|
31115
|
+
#tokenView(method, ctx, authority) {
|
|
31116
|
+
const view = actionView(ctx, authority, void 0);
|
|
31117
|
+
if (view === void 0) {
|
|
31118
|
+
this.#log("warn", "action.token.refused", {
|
|
31119
|
+
method,
|
|
31120
|
+
reason: "not the human tier"
|
|
31121
|
+
});
|
|
31122
|
+
throw new MessagingError("forbidden", `${method} takes an action token only on the human tier`);
|
|
31123
|
+
}
|
|
31124
|
+
return view;
|
|
31125
|
+
}
|
|
31126
|
+
#requestToken(method, p, ctx, authority, use) {
|
|
31127
|
+
if (p.token === void 0) {
|
|
31128
|
+
if (this.#jellyHost === void 0) return;
|
|
31129
|
+
this.#log("warn", "action.token.refused", {
|
|
31130
|
+
method,
|
|
31131
|
+
reason: "missing"
|
|
31132
|
+
});
|
|
31133
|
+
throw new MessagingError("grant_required", `${method} under a Jelly host needs the request's action token from request.list`);
|
|
31134
|
+
}
|
|
31135
|
+
this.#useToken(method, p.token, {
|
|
31136
|
+
name: p.answer,
|
|
31137
|
+
target: `request:${p.id}`,
|
|
31138
|
+
view: this.#tokenView(method, ctx, authority)
|
|
31139
|
+
}, use);
|
|
31140
|
+
}
|
|
31141
|
+
#useToken(method, token, want, use) {
|
|
31142
|
+
try {
|
|
31143
|
+
if (use === "redeem") this.#actions.redeem(token, want);
|
|
31144
|
+
else this.#actions.check(token, want);
|
|
31145
|
+
} catch (error) {
|
|
31146
|
+
this.#log("warn", "action.token.refused", {
|
|
31147
|
+
method,
|
|
31148
|
+
reason: "no matching live token"
|
|
31149
|
+
});
|
|
31150
|
+
throw error;
|
|
31151
|
+
}
|
|
31152
|
+
}
|
|
31153
|
+
actionTokens() {
|
|
31154
|
+
return this.#actions.size;
|
|
31155
|
+
}
|
|
31156
|
+
#withActions(request, view) {
|
|
31157
|
+
if (request.kind === "contact" && request.state !== "pending") return request;
|
|
31158
|
+
const names = request.kind === "suggestion" ? ["decline"] : request.kind === "contact" ? [
|
|
31159
|
+
"accept",
|
|
31160
|
+
"decline",
|
|
31161
|
+
"block"
|
|
31162
|
+
] : request.kind === "agent-invitation" ? ["accept", "decline"] : [
|
|
31163
|
+
"once",
|
|
31164
|
+
"always",
|
|
31165
|
+
"decline",
|
|
31166
|
+
"block"
|
|
31167
|
+
];
|
|
31168
|
+
return {
|
|
31169
|
+
...request,
|
|
31170
|
+
actions: names.map((name) => ({
|
|
31171
|
+
name,
|
|
31172
|
+
token: this.#actions.offer(view, name, `request:${request.id}`)
|
|
31173
|
+
}))
|
|
31174
|
+
};
|
|
30318
31175
|
}
|
|
30319
|
-
|
|
31176
|
+
taskCancel(row, role, view) {
|
|
31177
|
+
return taskCancelAction(this.#actions, {
|
|
31178
|
+
id: row.record.task.id,
|
|
31179
|
+
role,
|
|
31180
|
+
ended: isTerminal(row.record.task.status.state)
|
|
31181
|
+
}, view);
|
|
31182
|
+
}
|
|
31183
|
+
async #cancelByToken(p, token, view) {
|
|
30320
31184
|
this.#joined();
|
|
30321
|
-
|
|
30322
|
-
|
|
31185
|
+
this.#useToken("task.cancel", token, {
|
|
31186
|
+
name: "cancel",
|
|
31187
|
+
target: `task:${p.taskId}`,
|
|
31188
|
+
view
|
|
31189
|
+
}, "redeem");
|
|
31190
|
+
const row = this.#store.task(p.taskId, "requester");
|
|
31191
|
+
if (row === void 0) throw new MessagingError("not_found", "no task this person's agent asked has that id");
|
|
31192
|
+
return this.#cancelRow(row, p, true);
|
|
31193
|
+
}
|
|
31194
|
+
async #cancelRow(row, p, owner) {
|
|
31195
|
+
const { token: _token, ...scanned } = p;
|
|
31196
|
+
this.#refuseSecrets(scanned, "task.cancel", "task cancel");
|
|
30323
31197
|
if (isTerminal(row.record.task.status.state)) throw new MessagingError("invalid_state", "the task is in a terminal state");
|
|
30324
31198
|
const env = this.#tx(() => {
|
|
30325
31199
|
const env = this.#seal("task.cancel", row.record.peer.device, this.#sessionName(row), {
|
|
@@ -30330,10 +31204,123 @@ var init_daemon = __esmMin((() => {
|
|
|
30330
31204
|
return env;
|
|
30331
31205
|
});
|
|
30332
31206
|
await this.#settle([env.id]);
|
|
30333
|
-
return boundedRecord(this.#store.task(p.taskId, "requester")?.record ?? row.record, TASK_BYTES);
|
|
31207
|
+
return this.#withQuestion(await this.#viewNamed(boundedRecord(this.#store.task(p.taskId, "requester")?.record ?? row.record, TASK_BYTES)), owner);
|
|
31208
|
+
}
|
|
31209
|
+
async #nameOf(person) {
|
|
31210
|
+
const realm = this.#realm ?? this.#directory?.realm;
|
|
31211
|
+
if (!realm) return this.#named.get(person);
|
|
31212
|
+
let named;
|
|
31213
|
+
try {
|
|
31214
|
+
const profile = await realm.profile(person);
|
|
31215
|
+
named = {
|
|
31216
|
+
name: profile.name,
|
|
31217
|
+
org: profile.org
|
|
31218
|
+
};
|
|
31219
|
+
} catch (error) {
|
|
31220
|
+
if (!(error instanceof MessagingError) || error.code !== "not_found") return this.#named.get(person);
|
|
31221
|
+
named = {
|
|
31222
|
+
name: person,
|
|
31223
|
+
org: "none"
|
|
31224
|
+
};
|
|
31225
|
+
}
|
|
31226
|
+
if (this.#named.size >= NAMED_PERSONS && !this.#named.has(person)) this.#named.clear();
|
|
31227
|
+
this.#named.set(person, named);
|
|
31228
|
+
return named;
|
|
31229
|
+
}
|
|
31230
|
+
#taskView(record) {
|
|
31231
|
+
const named = this.#named.get(record.peer.person);
|
|
31232
|
+
if (named === void 0) this.#nameOf(record.peer.person).catch(() => void 0);
|
|
31233
|
+
return withTaskView(record, this.#me(), named);
|
|
31234
|
+
}
|
|
31235
|
+
#setQuestion(p) {
|
|
31236
|
+
const row = this.#ownTask(p.key, p.taskId, "executor");
|
|
31237
|
+
if (p.question === null) {
|
|
31238
|
+
if (this.#questions.delete(p.taskId)) this.#conversationIpc.taskChanged({
|
|
31239
|
+
id: p.taskId,
|
|
31240
|
+
role: "executor"
|
|
31241
|
+
});
|
|
31242
|
+
return { ok: true };
|
|
31243
|
+
}
|
|
31244
|
+
if (!isInterrupted(row.record.task.status.state)) throw new MessagingError("invalid_state", "only a task in auth-required or input-required waits on a question");
|
|
31245
|
+
const host = this.#store.sessionHost(p.key);
|
|
31246
|
+
if (host !== void 0 && host.sessionID !== p.question.sessionId) throw new MessagingError("forbidden", "a question names the session's own host session");
|
|
31247
|
+
this.#questions.set(p.taskId, {
|
|
31248
|
+
sessionId: p.question.sessionId,
|
|
31249
|
+
approvalId: p.question.approvalId
|
|
31250
|
+
});
|
|
31251
|
+
this.#conversationIpc.taskChanged({
|
|
31252
|
+
id: p.taskId,
|
|
31253
|
+
role: "executor"
|
|
31254
|
+
});
|
|
31255
|
+
return { ok: true };
|
|
31256
|
+
}
|
|
31257
|
+
async #personTask(row, view) {
|
|
31258
|
+
const { key: _key, ...rest } = this.#withQuestion(await this.#viewNamed(this.#withFollowUps(boundedRecord(row.record, TASK_BYTES))), true);
|
|
31259
|
+
const cancel = this.taskCancel(row, row.record.role, view);
|
|
31260
|
+
return {
|
|
31261
|
+
...rest,
|
|
31262
|
+
session: this.#sessionName(row),
|
|
31263
|
+
...cancel ? { cancel } : {}
|
|
31264
|
+
};
|
|
31265
|
+
}
|
|
31266
|
+
async #personTasks(p, view) {
|
|
31267
|
+
const limit = p.limit ?? 50;
|
|
31268
|
+
const key = p.session === void 0 ? void 0 : this.#store.sessionByName(p.session)?.key;
|
|
31269
|
+
if (p.session !== void 0 && key === void 0) return {
|
|
31270
|
+
tasks: [],
|
|
31271
|
+
total: 0
|
|
31272
|
+
};
|
|
31273
|
+
const { rows, total, more } = this.#store.listTasks({
|
|
31274
|
+
...key !== void 0 ? { key } : {},
|
|
31275
|
+
role: p.role,
|
|
31276
|
+
state: p.state,
|
|
31277
|
+
after: p.cursor === void 0 ? void 0 : decodeCursor(p.cursor),
|
|
31278
|
+
limit
|
|
31279
|
+
});
|
|
31280
|
+
const tasks = [];
|
|
31281
|
+
let bytes = 0;
|
|
31282
|
+
for (const row of rows) {
|
|
31283
|
+
const task = await this.#personTask(row, view);
|
|
31284
|
+
const size = jsonBytes(task);
|
|
31285
|
+
if (tasks.length > 0 && bytes + size > LIST_BYTES) break;
|
|
31286
|
+
tasks.push(task);
|
|
31287
|
+
bytes += size;
|
|
31288
|
+
}
|
|
31289
|
+
const last = tasks.at(-1);
|
|
31290
|
+
return {
|
|
31291
|
+
tasks,
|
|
31292
|
+
total,
|
|
31293
|
+
...(more || tasks.length < rows.length) && last ? { nextCursor: encodeCursor({
|
|
31294
|
+
updatedAt: last.updatedAt,
|
|
31295
|
+
taskId: last.task.id,
|
|
31296
|
+
role: last.role
|
|
31297
|
+
}) } : {}
|
|
31298
|
+
};
|
|
31299
|
+
}
|
|
31300
|
+
async #personTaskGet(p, view) {
|
|
31301
|
+
const rows = (p.role !== void 0 ? [p.role] : ["requester", "executor"]).flatMap((role) => this.#store.task(p.taskId, role) ?? []);
|
|
31302
|
+
if (rows.length === 0) throw new MessagingError("not_found", "no task of this person's agents has that id");
|
|
31303
|
+
if (rows.length > 1) throw new MessagingError("invalid_request", "this device holds both sides of that task; supply role");
|
|
31304
|
+
return await this.#personTask(rows[0], view);
|
|
31305
|
+
}
|
|
31306
|
+
async #personTaskEntry(id, role, ctx, authority) {
|
|
31307
|
+
const row = this.#store.task(id, role);
|
|
31308
|
+
return row ? await this.#personTask(row, actionView(ctx, authority, void 0)) : void 0;
|
|
31309
|
+
}
|
|
31310
|
+
#withQuestion(view, owner) {
|
|
31311
|
+
const question = this.#questions.get(view.task.id);
|
|
31312
|
+
if (!owner || question === void 0 || view.role !== "executor" || !isInterrupted(view.task.status.state)) return view;
|
|
31313
|
+
return {
|
|
31314
|
+
...view,
|
|
31315
|
+
question: { ...question }
|
|
31316
|
+
};
|
|
31317
|
+
}
|
|
31318
|
+
async #viewNamed(record) {
|
|
31319
|
+
return withTaskView(record, this.#me(), await this.#nameOf(record.peer.person).catch(() => void 0));
|
|
30334
31320
|
}
|
|
30335
31321
|
sweep() {
|
|
30336
31322
|
if (this.#closed) return;
|
|
31323
|
+
this.#actions.sweep();
|
|
30337
31324
|
this.#directory?.sweep();
|
|
30338
31325
|
const now = this.#now();
|
|
30339
31326
|
this.#expireTickets(now);
|
|
@@ -30383,6 +31370,7 @@ var init_daemon = __esmMin((() => {
|
|
|
30383
31370
|
message: agentMessage([{ text: INPUT_TIMEOUT_TEXT }], row.record.task.id, row.record.task.contextId, now),
|
|
30384
31371
|
timestamp: iso(now)
|
|
30385
31372
|
};
|
|
31373
|
+
this.#questions.delete(row.record.task.id);
|
|
30386
31374
|
row.record.task.status = status;
|
|
30387
31375
|
row.record.updatedAt = now;
|
|
30388
31376
|
this.#store.putTask(row);
|
|
@@ -30390,24 +31378,7 @@ var init_daemon = __esmMin((() => {
|
|
|
30390
31378
|
this.#sendStatus(row);
|
|
30391
31379
|
}
|
|
30392
31380
|
async #ensureCurrent(persons) {
|
|
30393
|
-
|
|
30394
|
-
const others = [...new Set(persons)].filter((p) => p !== own);
|
|
30395
|
-
if (!others.length) return;
|
|
30396
|
-
let outdated;
|
|
30397
|
-
try {
|
|
30398
|
-
outdated = (await this.#transport?.conversations?.convCaps?.(others))?.outdated ?? [];
|
|
30399
|
-
} catch {
|
|
30400
|
-
return;
|
|
30401
|
-
}
|
|
30402
|
-
if (!outdated.length) return;
|
|
30403
|
-
const handles = await Promise.all(outdated.map(async (p) => {
|
|
30404
|
-
try {
|
|
30405
|
-
return (await this.#joined().realm.profile(p)).handle;
|
|
30406
|
-
} catch {
|
|
30407
|
-
return p;
|
|
30408
|
-
}
|
|
30409
|
-
}));
|
|
30410
|
-
throw new MessagingError("peer_outdated", `${handles.join(", ")} ${handles.length === 1 ? "needs" : "need"} to update Messaging`);
|
|
31381
|
+
await ensureCurrent(this.#transport?.conversations, this.#joined().me.person, persons, async (p) => (await this.#joined().realm.profile(p)).handle);
|
|
30411
31382
|
}
|
|
30412
31383
|
conversations() {
|
|
30413
31384
|
return this.#conversationEngine();
|
|
@@ -30767,6 +31738,15 @@ var init_daemon = __esmMin((() => {
|
|
|
30767
31738
|
self: d.machine === identity.machine
|
|
30768
31739
|
})) };
|
|
30769
31740
|
}
|
|
31741
|
+
#withFeatures(d) {
|
|
31742
|
+
const raw = d.self ? [...FEATURES] : this.#store.directoryRow(d.device)?.presence.features;
|
|
31743
|
+
if (raw === void 0) return d;
|
|
31744
|
+
const features = [...new Set(raw.filter((f) => PresenceFeature.safeParse(f).success))].slice(0, 32);
|
|
31745
|
+
return {
|
|
31746
|
+
...d,
|
|
31747
|
+
features
|
|
31748
|
+
};
|
|
31749
|
+
}
|
|
30770
31750
|
#away() {
|
|
30771
31751
|
return this.#jellyHost !== void 0 && !this.#attached;
|
|
30772
31752
|
}
|
|
@@ -30798,23 +31778,49 @@ var init_daemon = __esmMin((() => {
|
|
|
30798
31778
|
if (issuer === void 0 || new URL(p.url).origin !== new URL(issuer).origin) throw new MessagingError("invalid_request", "the wake URL is not on the realm's Jelly ID");
|
|
30799
31779
|
const agents = [...new Set(p.agents)];
|
|
30800
31780
|
const awaiting = this.#store.awaitedRequests(agents, TERMINAL_STATES, 500);
|
|
31781
|
+
const dms = await this.#wakeDms();
|
|
30801
31782
|
const sent = await home.wake({
|
|
30802
31783
|
url: p.url,
|
|
30803
31784
|
ticket: p.ticket,
|
|
30804
31785
|
agents,
|
|
30805
|
-
awaiting
|
|
31786
|
+
awaiting,
|
|
31787
|
+
dms
|
|
30806
31788
|
});
|
|
30807
31789
|
this.#wakeArmed = true;
|
|
30808
31790
|
this.#log("info", "wake.arm", {
|
|
30809
31791
|
relay: sent === "sent" ? "armed" : "pending",
|
|
30810
31792
|
agents: agents.length,
|
|
30811
|
-
awaiting: awaiting.length
|
|
31793
|
+
awaiting: awaiting.length,
|
|
31794
|
+
dms: dms.length
|
|
30812
31795
|
});
|
|
30813
31796
|
return {
|
|
30814
31797
|
relay: sent === "sent" ? "armed" : "pending",
|
|
30815
|
-
awaiting: awaiting.length
|
|
31798
|
+
awaiting: awaiting.length,
|
|
31799
|
+
dms: dms.length
|
|
30816
31800
|
};
|
|
30817
31801
|
}
|
|
31802
|
+
async #wakeDms() {
|
|
31803
|
+
const engine = this.#conversationEngine();
|
|
31804
|
+
if (!engine) return [];
|
|
31805
|
+
const { me, realm } = this.#joined();
|
|
31806
|
+
const orgs = new Map();
|
|
31807
|
+
const orgOf = (person) => {
|
|
31808
|
+
let org = orgs.get(person);
|
|
31809
|
+
if (!org) orgs.set(person, org = realm.profile(person).then((profile) => profile.org, () => "none"));
|
|
31810
|
+
return org;
|
|
31811
|
+
};
|
|
31812
|
+
const candidates = teammateDms(engine.list(), me.person);
|
|
31813
|
+
await realm.freshen?.(candidates.map((c) => c.person)).catch(() => {});
|
|
31814
|
+
const dms = [];
|
|
31815
|
+
for (const { cid, person } of candidates) {
|
|
31816
|
+
if (dms.length >= 256) break;
|
|
31817
|
+
if (this.#shouldArm(person, await orgOf(person))) dms.push(cid);
|
|
31818
|
+
}
|
|
31819
|
+
return dms;
|
|
31820
|
+
}
|
|
31821
|
+
#shouldArm(person, org) {
|
|
31822
|
+
return wakeArmable(this.#grants, person, org);
|
|
31823
|
+
}
|
|
30818
31824
|
async #wakeDisarm() {
|
|
30819
31825
|
const home = this.#directory;
|
|
30820
31826
|
if (!home) throw new MessagingError("invalid_state", "wake tickets are for a directory realm");
|
|
@@ -31625,6 +32631,7 @@ var init_daemon = __esmMin((() => {
|
|
|
31625
32631
|
}
|
|
31626
32632
|
};
|
|
31627
32633
|
LIST_BYTES = 1572864;
|
|
32634
|
+
NAMED_PERSONS = 1e3;
|
|
31628
32635
|
}));
|
|
31629
32636
|
// node_modules/ws/lib/constants.js
|
|
31630
32637
|
var require_constants = __commonJSMin(((exports, module) => {
|
|
@@ -34164,7 +35171,8 @@ var init_pages = __esmMin((() => {
|
|
|
34164
35171
|
var init_store$2 = __esmMin((() => {
|
|
34165
35172
|
init_dist$3();
|
|
34166
35173
|
({DatabaseSync} = process.getBuiltinModule("node:sqlite"));
|
|
34167
|
-
MIGRATIONS = [
|
|
35174
|
+
MIGRATIONS = [
|
|
35175
|
+
`
|
|
34168
35176
|
CREATE TABLE IF NOT EXISTS conv_logs (
|
|
34169
35177
|
realm TEXT NOT NULL,
|
|
34170
35178
|
cid TEXT NOT NULL,
|
|
@@ -34215,7 +35223,8 @@ CREATE TABLE IF NOT EXISTS conv_shares (
|
|
|
34215
35223
|
CREATE INDEX IF NOT EXISTS conv_shares_to ON conv_shares (realm, cid, to_device, n);
|
|
34216
35224
|
CREATE INDEX IF NOT EXISTS conv_shares_pair ON conv_shares (realm, cid, from_device, to_device);
|
|
34217
35225
|
CREATE INDEX IF NOT EXISTS conv_shares_at ON conv_shares (at);
|
|
34218
|
-
`,
|
|
35226
|
+
`,
|
|
35227
|
+
`
|
|
34219
35228
|
CREATE TABLE IF NOT EXISTS conv_request_decisions (
|
|
34220
35229
|
realm TEXT NOT NULL,
|
|
34221
35230
|
id TEXT NOT NULL,
|
|
@@ -34223,7 +35232,17 @@ CREATE TABLE IF NOT EXISTS conv_request_decisions (
|
|
|
34223
35232
|
decision TEXT NOT NULL,
|
|
34224
35233
|
PRIMARY KEY (realm, id)
|
|
34225
35234
|
);
|
|
34226
|
-
|
|
35235
|
+
`,
|
|
35236
|
+
`
|
|
35237
|
+
CREATE TABLE IF NOT EXISTS dir_wake_dms (
|
|
35238
|
+
device TEXT NOT NULL,
|
|
35239
|
+
cid TEXT NOT NULL,
|
|
35240
|
+
exp INTEGER NOT NULL,
|
|
35241
|
+
PRIMARY KEY (device, cid)
|
|
35242
|
+
);
|
|
35243
|
+
CREATE INDEX IF NOT EXISTS dir_wake_dms_exp ON dir_wake_dms (exp);
|
|
35244
|
+
`
|
|
35245
|
+
];
|
|
34227
35246
|
1 + MIGRATIONS.length;
|
|
34228
35247
|
}));
|
|
34229
35248
|
// packages/relay/dist/backoff.js
|
|
@@ -34879,7 +35898,8 @@ var init_client = __esmMin((() => {
|
|
|
34879
35898
|
url: arm.url,
|
|
34880
35899
|
ticket: arm.ticket,
|
|
34881
35900
|
agents: arm.agents,
|
|
34882
|
-
awaiting: arm.awaiting
|
|
35901
|
+
awaiting: arm.awaiting,
|
|
35902
|
+
...arm.dms ? { dms: arm.dms } : {}
|
|
34883
35903
|
});
|
|
34884
35904
|
}
|
|
34885
35905
|
wakeDisarm() {
|