@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.
Files changed (50) hide show
  1. package/CHANGELOG.md +150 -0
  2. package/dist/bin/messaging-mcp.js +202 -31
  3. package/dist/bin/messaging-relay.js +291 -43
  4. package/dist/bin/messaging.js +290 -32
  5. package/dist/bin/messagingd.js +1158 -138
  6. package/dist/lib/modules/core/agent/present.js +5 -0
  7. package/dist/lib/modules/core/agent-tools.js +12 -0
  8. package/dist/lib/modules/core/consent.js +54 -14
  9. package/dist/lib/modules/core/contact-card.js +3 -3
  10. package/dist/lib/modules/core/index.js +1 -1
  11. package/dist/lib/modules/core/jelly-host.js +3 -0
  12. package/dist/lib/modules/core/schema/common.js +2 -0
  13. package/dist/lib/modules/core/schema/consent.js +20 -3
  14. package/dist/lib/modules/core/schema/conv-frames.js +10 -3
  15. package/dist/lib/modules/core/schema/directory-frames.js +8 -3
  16. package/dist/lib/modules/core/schema/errors.js +3 -2
  17. package/dist/lib/modules/core/schema/ipc/consent.js +85 -10
  18. package/dist/lib/modules/core/schema/ipc/conversation-views.js +8 -1
  19. package/dist/lib/modules/core/schema/ipc/conversations.js +5 -1
  20. package/dist/lib/modules/core/schema/ipc/device.js +7 -0
  21. package/dist/lib/modules/core/schema/ipc/jelly.js +14 -7
  22. package/dist/lib/modules/core/schema/ipc/shapes.js +60 -1
  23. package/dist/lib/modules/core/schema/ipc.js +51 -3
  24. package/dist/lib/modules/core/version.js +1 -1
  25. package/dist/spec/messaging-v1.md +321 -49
  26. package/dist/types/core/agent/present.d.ts +1 -1
  27. package/dist/types/core/agent-tools.d.ts +32 -0
  28. package/dist/types/core/consent.d.ts +30 -7
  29. package/dist/types/core/contact-card.d.ts +3 -3
  30. package/dist/types/core/conversation-agent-tools.d.ts +21 -0
  31. package/dist/types/core/index.d.ts +1 -1
  32. package/dist/types/core/schema/common.d.ts +2 -0
  33. package/dist/types/core/schema/consent.d.ts +23 -2
  34. package/dist/types/core/schema/conv-frames.d.ts +6 -2
  35. package/dist/types/core/schema/directory-frames.d.ts +8 -3
  36. package/dist/types/core/schema/envelope.d.ts +2 -0
  37. package/dist/types/core/schema/errors.d.ts +2 -0
  38. package/dist/types/core/schema/ipc/consent.d.ts +377 -15
  39. package/dist/types/core/schema/ipc/conversation-views.d.ts +176 -0
  40. package/dist/types/core/schema/ipc/conversations.d.ts +368 -0
  41. package/dist/types/core/schema/ipc/device.d.ts +6 -0
  42. package/dist/types/core/schema/ipc/jelly.d.ts +14 -6
  43. package/dist/types/core/schema/ipc/shapes.d.ts +198 -0
  44. package/dist/types/core/schema/ipc/surfaces.d.ts +1 -0
  45. package/dist/types/core/schema/ipc/tasks.d.ts +2 -0
  46. package/dist/types/core/schema/ipc.d.ts +826 -3
  47. package/dist/types/core/schema/relay.d.ts +4 -0
  48. package/dist/types/core/version.d.ts +1 -1
  49. package/dist/types/ipc/server.d.ts +6 -0
  50. package/package.json +1 -1
@@ -5678,7 +5678,8 @@ const DOMAIN = {
5678
5678
  const URI = {
5679
5679
  binding: "urn:messaging:binding:relay:v1",
5680
5680
  provenance: "urn:messaging:ext:provenance:v1",
5681
- presence: "urn:messaging:ext:presence:v1"
5681
+ presence: "urn:messaging:ext:presence:v1",
5682
+ signIn: "urn:messaging:ext:sign-in:v1"
5682
5683
  };
5683
5684
  const Base64Url = string$1().regex(/^[A-Za-z0-9_-]*$/, "base64url without padding");
5684
5685
  const Key32 = string$1().regex(/^[A-Za-z0-9_-]{43}$/, "32 bytes, base64url without padding");
@@ -5849,6 +5850,7 @@ const ErrorCode = _enum([
5849
5850
  "jelly_unavailable",
5850
5851
  "log_conflict",
5851
5852
  "conv_conflict",
5853
+ "conflict",
5852
5854
  "stale_epoch",
5853
5855
  "device_limit",
5854
5856
  "admission_required",
@@ -6797,7 +6799,12 @@ const AskLevel = _enum([
6797
6799
  "request",
6798
6800
  "no"
6799
6801
  ]);
6800
- const GrantSubject = union$1([strictObject({ person: PersonId }), strictObject({ conv: ConvId })]);
6802
+ const GrantRelation = _enum(["outside", "org"]);
6803
+ const GrantSubject = union$1([
6804
+ strictObject({ person: PersonId }),
6805
+ strictObject({ conv: ConvId }),
6806
+ strictObject({ relation: GrantRelation })
6807
+ ]);
6801
6808
  object({
6802
6809
  v: literal(PROTOCOL),
6803
6810
  realm: RealmId,
@@ -6824,6 +6831,12 @@ const GrantSync = strictObject({ grants: array(record(string$1(), unknown())).mi
6824
6831
  function grantProblem(grant) {
6825
6832
  const own = "person" in grant.subject && grant.subject.person === grant.person;
6826
6833
  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";
6834
+ if ("relation" in grant.subject) {
6835
+ if (grant.agentMail !== void 0 || grant.trustedUntil !== void 0 || grant.discoverable !== void 0) return "a relation grant sets only chat or ask";
6836
+ if (grant.subject.relation === "outside" && grant.ask !== void 0) return "the outside relation grant sets only chat";
6837
+ if (grant.subject.relation === "outside" && grant.chat === "muted") return "the outside relation grant sets chat open or blocked";
6838
+ if (grant.subject.relation === "org" && grant.chat !== void 0) return "the org relation grant sets only ask";
6839
+ }
6827
6840
  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";
6828
6841
  if (!own && grant.discoverable !== void 0) return "discoverable is set only on a grant about its own person";
6829
6842
  if (grant.trustedUntil !== void 0) {
@@ -7288,7 +7301,8 @@ discriminatedUnion("t", [
7288
7301
  url: WakeUrl,
7289
7302
  ticket: Jws.refine((ticket) => ticket.length <= WAKE_TICKET_BYTES, { message: `at most ${WAKE_TICKET_BYTES} bytes` }),
7290
7303
  agents: array(SessionName).max(64),
7291
- awaiting: array(Ulid).max(500)
7304
+ awaiting: array(Ulid).max(500),
7305
+ dms: array(ConvId).max(256).optional()
7292
7306
  }),
7293
7307
  object({
7294
7308
  t: literal("wake.disarm"),
@@ -7403,6 +7417,7 @@ const DeviceChangeView = object({
7403
7417
  approver: MachineLabel.optional(),
7404
7418
  at: Millis
7405
7419
  });
7420
+ const PresenceFeature = string$1().regex(/^[a-z][a-z0-9-]{0,31}$/, "a feature name");
7406
7421
  const DeviceListEntry = object({
7407
7422
  device: MachineId,
7408
7423
  label: MachineLabel,
@@ -7421,7 +7436,8 @@ const DeviceListEntry = object({
7421
7436
  at: Millis,
7422
7437
  reason: UnbindReason,
7423
7438
  by: MachineId
7424
- }).optional()
7439
+ }).optional(),
7440
+ features: array(PresenceFeature).max(32).optional()
7425
7441
  });
7426
7442
  const LinkText = string$1().min(1).max(2048);
7427
7443
  const Sas = string$1().regex(/^[0-9]{6}$/, "six digits");
@@ -7628,6 +7644,7 @@ const DEVICE_METHODS = {
7628
7644
  };
7629
7645
  // packages/core/dist/schema/ipc/shapes.js
7630
7646
  const SessionKey = string$1().min(1).max(200);
7647
+ const ActionToken = string$1().regex(/^[A-Za-z0-9_-]{43}$/, "action token");
7631
7648
  const SendExpect = _enum([
7632
7649
  "next_turn",
7633
7650
  "wake",
@@ -7698,7 +7715,14 @@ const TaskFollowUp = object({
7698
7715
  stage: DeliveryStage,
7699
7716
  at: Millis
7700
7717
  });
7701
- const TaskRecord = object({
7718
+ const TASK_SIGN_IN_TOOL_CHARS = LIMITS.previewChars;
7719
+ const TASK_REFUSAL_CHARS = LIMITS.requestChars;
7720
+ const HostLocalId = string$1().regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,199}$/, "a plain identifier of at most 200 characters");
7721
+ const TaskQuestion = strictObject({
7722
+ sessionId: HostLocalId,
7723
+ approvalId: HostLocalId
7724
+ });
7725
+ const TaskRecordFields = object({
7702
7726
  task: Task$1.extend({ id: Ulid }),
7703
7727
  role: _enum(["requester", "executor"]),
7704
7728
  key: SessionKey.describe("local session that owns this side of the task"),
@@ -7706,8 +7730,36 @@ const TaskRecord = object({
7706
7730
  createdAt: Millis,
7707
7731
  updatedAt: Millis,
7708
7732
  chain: DelegationSummary.optional(),
7709
- followUps: array(TaskFollowUp).min(1).max(LIMITS.taskFollowUps).optional()
7710
- });
7733
+ followUps: array(TaskFollowUp).min(1).max(LIMITS.taskFollowUps).optional(),
7734
+ agent: SessionName.optional(),
7735
+ person: object({
7736
+ id: PersonId,
7737
+ name: string$1().max(200)
7738
+ }).optional(),
7739
+ org: _enum([
7740
+ "same",
7741
+ "other",
7742
+ "none"
7743
+ ]).optional(),
7744
+ signIn: object({
7745
+ tool: string$1().min(1).max(TASK_SIGN_IN_TOOL_CHARS).optional(),
7746
+ by: _enum(["you", "them"])
7747
+ }).optional(),
7748
+ refusal: object({ reason: string$1().min(1).max(TASK_REFUSAL_CHARS) }).optional(),
7749
+ question: TaskQuestion.optional()
7750
+ });
7751
+ function taskViewRules(schema) {
7752
+ 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");
7753
+ }
7754
+ const TaskRecord = taskViewRules(TaskRecordFields);
7755
+ const PersonTask = taskViewRules(TaskRecordFields.omit({ key: true }).extend({
7756
+ key: never().optional(),
7757
+ session: SessionName.describe("this person's agent on this device that holds this side of the task"),
7758
+ cancel: strictObject({
7759
+ name: literal("cancel"),
7760
+ token: ActionToken
7761
+ }).optional()
7762
+ })).refine((r) => r.cancel === void 0 || r.role === "requester", "cancel is for the requester side");
7711
7763
  const SendTarget = SessionAddress;
7712
7764
  const SendResult = object({
7713
7765
  to: SendTarget,
@@ -7750,6 +7802,17 @@ const GrantSetParams = strictObject({
7750
7802
  ...Levels,
7751
7803
  trust: literal(true).optional()
7752
7804
  });
7805
+ const RequestAnswer = _enum([
7806
+ "once",
7807
+ "always",
7808
+ "accept",
7809
+ "decline",
7810
+ "block"
7811
+ ]);
7812
+ const Actions = { actions: array(strictObject({
7813
+ name: RequestAnswer,
7814
+ token: ActionToken
7815
+ })).max(4).optional() };
7753
7816
  const AskRequest = object({
7754
7817
  id: Ulid,
7755
7818
  kind: _enum(["message", "task"]),
@@ -7763,7 +7826,8 @@ const AskRequest = object({
7763
7826
  to: SessionName,
7764
7827
  preview: string$1().max(LIMITS.previewChars),
7765
7828
  at: Millis,
7766
- exp: Millis
7829
+ exp: Millis,
7830
+ ...Actions
7767
7831
  });
7768
7832
  const ContactRequestView = object({
7769
7833
  id: Ulid,
@@ -7789,7 +7853,8 @@ const ContactRequestView = object({
7789
7853
  }),
7790
7854
  text: string$1().max(LIMITS.requestChars),
7791
7855
  at: Millis,
7792
- exp: Millis
7856
+ exp: Millis,
7857
+ ...Actions
7793
7858
  });
7794
7859
  const AgentInvitationRequest = strictObject({
7795
7860
  kind: literal("agent-invitation"),
@@ -7797,7 +7862,8 @@ const AgentInvitationRequest = strictObject({
7797
7862
  cid: ConvId,
7798
7863
  from: ParticipantId,
7799
7864
  to: ParticipantId,
7800
- at: Millis
7865
+ at: Millis,
7866
+ ...Actions
7801
7867
  });
7802
7868
  const HeldRequest = union$1([
7803
7869
  AskRequest,
@@ -7807,17 +7873,11 @@ const HeldRequest = union$1([
7807
7873
  kind: literal("suggestion"),
7808
7874
  agent: SessionName,
7809
7875
  email: Email,
7810
- at: Millis
7876
+ at: Millis,
7877
+ ...Actions
7811
7878
  }),
7812
7879
  AgentInvitationRequest
7813
7880
  ]);
7814
- const RequestAnswer = _enum([
7815
- "once",
7816
- "always",
7817
- "accept",
7818
- "decline",
7819
- "block"
7820
- ]);
7821
7881
  const RequestText = string$1().min(1).refine((text) => text.length <= LIMITS.requestChars, { message: `at most ${LIMITS.requestChars} UTF-16 code units` });
7822
7882
  const PersonReach = object({
7823
7883
  person: PersonId,
@@ -7829,14 +7889,57 @@ const PersonReach = object({
7829
7889
  const RequestAnswerParams = strictObject({
7830
7890
  id: Ulid,
7831
7891
  answer: RequestAnswer,
7832
- all: boolean().optional()
7833
- });
7892
+ all: boolean().optional(),
7893
+ token: ActionToken.optional()
7894
+ }).refine((p) => p.token === void 0 || p.all !== true, "an action token answers one request: drop all");
7834
7895
  const ContactRequestParams = strictObject({
7835
7896
  email: Email,
7836
7897
  text: RequestText,
7837
7898
  suggestion: Ulid.optional()
7838
7899
  });
7900
+ const ReachGroupId = _enum(["message", "ask"]);
7901
+ const ReachValue = _enum([
7902
+ "open",
7903
+ "ask",
7904
+ "never"
7905
+ ]);
7906
+ const ReachOption = object({
7907
+ value: ReachValue,
7908
+ label: string$1().max(40),
7909
+ description: string$1().max(300)
7910
+ });
7911
+ const ReachGroup = object({
7912
+ id: ReachGroupId,
7913
+ label: string$1().max(80),
7914
+ options: array(ReachOption).length(3),
7915
+ value: ReachValue.nullable(),
7916
+ lapsed: ReachValue.optional()
7917
+ });
7918
+ const ReachSnapshot = object({
7919
+ revision: string$1().min(1).max(64),
7920
+ available: boolean(),
7921
+ groups: array(ReachGroup).length(2)
7922
+ });
7923
+ const ReachSetParams = strictObject({
7924
+ revision: string$1().min(1).max(64),
7925
+ changes: strictObject({
7926
+ message: ReachValue.optional(),
7927
+ ask: ReachValue.optional()
7928
+ })
7929
+ });
7839
7930
  const CONSENT_METHODS = {
7931
+ "reach.get": {
7932
+ params: strictObject({}),
7933
+ result: ReachSnapshot
7934
+ },
7935
+ "reach.set": {
7936
+ params: ReachSetParams,
7937
+ result: ReachSnapshot
7938
+ },
7939
+ "reach.set.preview": {
7940
+ params: ReachSetParams,
7941
+ result: object({ sentence: string$1().max(500) })
7942
+ },
7840
7943
  "grant.list": {
7841
7944
  params: strictObject({ subject: GrantTarget.optional() }),
7842
7945
  result: object({
@@ -8000,6 +8103,7 @@ const Notice = object({
8000
8103
  }).optional(),
8001
8104
  line: string$1().max(120).optional(),
8002
8105
  device: NoticeDevice.optional(),
8106
+ key: string$1().regex(/^task:[0-9A-HJKMNP-TV-Z]{26}$/, "task:<task id>").optional(),
8003
8107
  at: Millis
8004
8108
  });
8005
8109
  const NoticeCounts = object({ requests: number$1().int().nonnegative() });
@@ -8070,7 +8174,8 @@ const JELLY_METHODS = {
8070
8174
  }),
8071
8175
  result: object({
8072
8176
  relay: _enum(["armed", "pending"]),
8073
- awaiting: number$1().int().nonnegative()
8177
+ awaiting: number$1().int().nonnegative(),
8178
+ dms: number$1().int().nonnegative()
8074
8179
  })
8075
8180
  },
8076
8181
  "wake.disarm": {
@@ -8183,7 +8288,11 @@ const FileView = object({
8183
8288
  });
8184
8289
  const TaskView = object({
8185
8290
  id: Ulid,
8186
- state: TaskState
8291
+ state: TaskState,
8292
+ cancel: strictObject({
8293
+ name: literal("cancel"),
8294
+ token: ActionToken
8295
+ }).optional()
8187
8296
  });
8188
8297
  const EventView = object({
8189
8298
  cid: ConvId,
@@ -8342,6 +8451,11 @@ const ConvStreamEvent = discriminatedUnion("type", [
8342
8451
  object({
8343
8452
  type: literal("gap"),
8344
8453
  pos: Seq$1
8454
+ }),
8455
+ object({
8456
+ type: literal("task"),
8457
+ pos: Seq$1,
8458
+ task: PersonTask
8345
8459
  })
8346
8460
  ]).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" });
8347
8461
  // packages/core/dist/schema/ipc/conversations.js
@@ -8448,7 +8562,12 @@ const WaitingOnThemView = object({
8448
8562
  at: Millis,
8449
8563
  cid: ConvId.optional(),
8450
8564
  agent: SessionName.optional(),
8451
- state: _enum(["held", "pending-delivery"])
8565
+ state: _enum([
8566
+ "held",
8567
+ "pending-delivery",
8568
+ "resend",
8569
+ "outdated"
8570
+ ])
8452
8571
  });
8453
8572
  const ConvListParams = strictObject({
8454
8573
  key: Key,
@@ -9063,16 +9182,47 @@ const IPC_METHODS = {
9063
9182
  message: strictObject({ parts: array(Part$1).min(1).max(LIMITS.partsPerMessage) }).optional(),
9064
9183
  artifact: Artifact.optional(),
9065
9184
  append: boolean().optional(),
9066
- lastChunk: boolean().optional()
9067
- }),
9185
+ lastChunk: boolean().optional(),
9186
+ signIn: strictObject({ tool: string$1().min(1).max(TASK_SIGN_IN_TOOL_CHARS) }).optional()
9187
+ }).refine((p) => p.signIn === void 0 || p.state === "TASK_STATE_AUTH_REQUIRED", "signIn goes with TASK_STATE_AUTH_REQUIRED"),
9068
9188
  result: TaskRecord
9069
9189
  },
9070
- "task.cancel": {
9190
+ "task.question": {
9071
9191
  params: strictObject({
9072
9192
  key: SessionKey,
9073
9193
  taskId: Ulid,
9074
- reason: string$1().max(1e3).optional()
9194
+ question: TaskQuestion.nullable()
9075
9195
  }),
9196
+ result: object({ ok: literal(true) })
9197
+ },
9198
+ "tasks.list": {
9199
+ params: strictObject({
9200
+ role: _enum(["requester", "executor"]).optional(),
9201
+ state: TaskState.optional(),
9202
+ session: SessionName.optional().describe("only this agent's tasks"),
9203
+ cursor: string$1().min(1).max(200).optional().describe("opaque; from a previous nextCursor"),
9204
+ limit: number$1().int().min(1).max(100).optional()
9205
+ }),
9206
+ result: object({
9207
+ tasks: array(PersonTask),
9208
+ nextCursor: string$1().max(200).optional().describe("absent when there are no more pages"),
9209
+ total: number$1().int().nonnegative()
9210
+ })
9211
+ },
9212
+ "tasks.get": {
9213
+ params: strictObject({
9214
+ taskId: Ulid,
9215
+ role: _enum(["requester", "executor"]).optional()
9216
+ }),
9217
+ result: PersonTask
9218
+ },
9219
+ "task.cancel": {
9220
+ params: strictObject({
9221
+ key: SessionKey.optional(),
9222
+ taskId: Ulid,
9223
+ reason: string$1().max(1e3).optional(),
9224
+ token: ActionToken.optional()
9225
+ }).refine((p) => p.key === void 0 !== (p.token === void 0), "give exactly one of key or token"),
9076
9226
  result: TaskRecord
9077
9227
  },
9078
9228
  "events.subscribe": {
@@ -9225,7 +9375,8 @@ const AGENT_METHODS = [
9225
9375
  "task.list",
9226
9376
  "task.get",
9227
9377
  "task.update",
9228
- "task.cancel"
9378
+ "task.cancel",
9379
+ "task.question"
9229
9380
  ];
9230
9381
  const HUMAN_METHODS = [
9231
9382
  ...conversationTier("human"),
@@ -9234,6 +9385,9 @@ const HUMAN_METHODS = [
9234
9385
  "grant.list",
9235
9386
  "grant.set",
9236
9387
  "grant.set.preview",
9388
+ "reach.get",
9389
+ "reach.set",
9390
+ "reach.set.preview",
9237
9391
  "request.list",
9238
9392
  "request.answer",
9239
9393
  "request.answer.preview",
@@ -9243,6 +9397,8 @@ const HUMAN_METHODS = [
9243
9397
  "notice.subscribe",
9244
9398
  "notice.list",
9245
9399
  "notice.ack",
9400
+ "tasks.list",
9401
+ "tasks.get",
9246
9402
  "device.approve.preview",
9247
9403
  "device.remove.preview",
9248
9404
  "identity.replace.preview",
@@ -9393,7 +9549,8 @@ strictObject({
9393
9549
  strictObject({
9394
9550
  t: literal("conv.capabilities"),
9395
9551
  req: Req,
9396
- outdated: array(PersonId).max(LIMITS.convOpParticipants)
9552
+ outdated: array(PersonId).max(LIMITS.convOpParticipants),
9553
+ unknown: array(PersonId).min(1).max(LIMITS.convOpParticipants).optional()
9397
9554
  });
9398
9555
  union$1([strictObject({
9399
9556
  t: literal("conv.push"),
@@ -9562,6 +9719,11 @@ const Task = object({
9562
9719
  titleAuthor: Author$1.optional().describe("With title: who wrote the request; ours when you asked (mine)"),
9563
9720
  status: authored("The latest status message").optional(),
9564
9721
  statusAuthor: Author$1.optional().describe("With status: who wrote it; ours when you run the task (asked)"),
9722
+ signIn: object({
9723
+ tool: authored("The tool the executor named").optional(),
9724
+ 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")
9725
+ }).optional().describe("auth_required only: the task waits on a sign-in; the tool was written by the executor, as statusAuthor says"),
9726
+ refusal: object({ reason: authored("The executor's reason") }).optional().describe("rejected only: why the executor declined, in its words, as statusAuthor says"),
9565
9727
  createdAt: iso$1,
9566
9728
  updatedAt: iso$1,
9567
9729
  consent: ToolConsentSchema.optional(),
@@ -9830,7 +9992,7 @@ function utf8(text) {
9830
9992
  return Buffer.from(text, "utf8");
9831
9993
  }
9832
9994
  // packages/core/dist/version.js
9833
- const VERSION = "0.8.0";
9995
+ const VERSION = "0.9.0";
9834
9996
  // packages/core/dist/jcs.js
9835
9997
  const LONE_SURROGATE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/;
9836
9998
  function hasLoneSurrogate(text) {
@@ -10244,8 +10406,11 @@ const VIEW_METHODS = [
10244
10406
  "people.search",
10245
10407
  "people.get",
10246
10408
  "grant.list",
10409
+ "reach.get",
10247
10410
  "request.list",
10248
10411
  "sessions.list",
10412
+ "tasks.list",
10413
+ "tasks.get",
10249
10414
  "notice.subscribe",
10250
10415
  "notice.list",
10251
10416
  "device.list"
@@ -12190,7 +12355,7 @@ var MessagingClient = class MessagingClient {
12190
12355
  timer = setTimeout(() => reject(new DaemonMismatchError(`the process on the Messaging daemon socket did not say which version it is within ${wait} ms: it is a messagingd from before this version, or it is stuck. ${REMEDY}`)), wait);
12191
12356
  })]);
12192
12357
  if (pointer !== void 0 && hello.pid !== pointer.pid) throw new MessagingError("forbidden", "the process on the Messaging daemon's pipe is not the daemon that published it");
12193
- const expected = options.version ?? "0.8.0";
12358
+ const expected = options.version ?? "0.9.0";
12194
12359
  if (hello.protocol !== 1 || hello.version !== expected) throw new DaemonMismatchError(`the Messaging daemon for this home is version ${shown(hello.version)} (IPC protocol ${hello.protocol}), and this client is version ${shown(expected)} (IPC protocol 1). ${REMEDY}`, hello);
12195
12360
  client.daemonHello = hello;
12196
12361
  return client;
@@ -12387,6 +12552,7 @@ const HINTS = {
12387
12552
  login_denied: "the sign-in was denied at Jelly ID; run messaging login again if it was you, or check the account.",
12388
12553
  log_conflict: "retry: the device log changed at the same time.",
12389
12554
  conv_conflict: "retry: the conversation changed at the same time.",
12555
+ conflict: "your settings changed at the same time: run the command again to see them, then choose again.",
12390
12556
  stale_epoch: "retry: the conversation's keys changed at the same time.",
12391
12557
  device_limit: "remove one of this person's devices first.",
12392
12558
  admission_required: "bind this device from Jelly, or approve it from one of your Jelly devices.",
@@ -13146,9 +13312,94 @@ const grant = {
13146
13312
  function optional(key, value) {
13147
13313
  return value === void 0 ? {} : { [key]: value };
13148
13314
  }
13315
+ function choiceLabel(group, value) {
13316
+ return group.options.find((o) => o.value === value)?.label ?? value;
13317
+ }
13318
+ function printReach(ctx, snapshot) {
13319
+ ctx.out.lines(table([
13320
+ "QUESTION",
13321
+ "CHOICE",
13322
+ "MEANS"
13323
+ ], snapshot.groups.map((g) => {
13324
+ const option = g.options.find((o) => o.value === (g.value ?? "ask"));
13325
+ return [
13326
+ g.label,
13327
+ g.value === null ? `${choiceLabel(g, "ask")} (the default)` : choiceLabel(g, g.value),
13328
+ option?.description ?? ""
13329
+ ];
13330
+ }), ctx.out.style));
13331
+ for (const g of snapshot.groups) if (g.lapsed !== void 0) ctx.out.line(ctx.out.style.yellow(`${g.label}: ${choiceLabel(g, g.lapsed)} lapsed with the device that chose it; choose again.`));
13332
+ }
13149
13333
  const CONSENT_COMMANDS = [
13150
13334
  grants,
13151
13335
  grant,
13336
+ {
13337
+ name: "reach",
13338
+ summary: "Show or set who can message you and how agents may ask yours: open, ask (me first) or never",
13339
+ usage: "[--message open|ask|never] [--ask open|ask|never] [--dry-run]",
13340
+ details: [
13341
+ "--message (Who can message you) is for people outside your org: open lets anyone message you; ask (the default)",
13342
+ "has them send a message request first; never refuses them and their requests. Your org can always message you.",
13343
+ "--ask (How agents may ask yours) is for your teammates' agents: open lets them ask your agents without asking you",
13344
+ "(guarded); ask (the default) holds each request for you (messaging requests); never refuses them. Agents of people",
13345
+ "outside your org never may. A grant you set for one person (messaging grant) wins over either choice.",
13346
+ "With no option it shows your choices. --dry-run prints what the change would do and changes nothing.",
13347
+ "A device of yours on an older Messaging release does not enforce these choices: update every device."
13348
+ ].join("\n"),
13349
+ options: {
13350
+ message: {
13351
+ type: "string",
13352
+ value: "open|ask|never",
13353
+ description: "Who can message you (people outside your org)"
13354
+ },
13355
+ ask: {
13356
+ type: "string",
13357
+ value: "open|ask|never",
13358
+ description: "How your teammates' agents may ask yours"
13359
+ },
13360
+ "dry-run": {
13361
+ type: "boolean",
13362
+ description: "Print what it would do and change nothing"
13363
+ }
13364
+ },
13365
+ args: {
13366
+ min: 0,
13367
+ max: 0
13368
+ },
13369
+ async run(ctx, _positionals, values) {
13370
+ const changes = {
13371
+ ...optional("message", levelOption(values, "message", ReachValue, "open, ask or never")),
13372
+ ...optional("ask", levelOption(values, "ask", ReachValue, "open, ask or never"))
13373
+ };
13374
+ const none = Object.keys(changes).length === 0;
13375
+ if (none && values["dry-run"] === true) throw new UsageError("--dry-run goes with --message or --ask");
13376
+ const client = await ctx.client();
13377
+ const shown = await client.call("reach.get", {});
13378
+ if (none) {
13379
+ if (ctx.json) return ctx.out.json(shown);
13380
+ printReach(ctx, shown);
13381
+ ctx.out.note("Change with: messaging reach --message open|ask|never --ask open|ask|never");
13382
+ return;
13383
+ }
13384
+ const params = {
13385
+ revision: shown.revision,
13386
+ changes
13387
+ };
13388
+ const { sentence } = await client.call("reach.set.preview", params);
13389
+ if (values["dry-run"] === true) {
13390
+ if (ctx.json) ctx.out.json({ sentence });
13391
+ else ctx.out.line(sentence);
13392
+ return;
13393
+ }
13394
+ const result = await client.call("reach.set", params);
13395
+ if (ctx.json) return ctx.out.json({
13396
+ sentence,
13397
+ ...result
13398
+ });
13399
+ ctx.out.line(sentence);
13400
+ printReach(ctx, result);
13401
+ }
13402
+ },
13152
13403
  {
13153
13404
  name: "requests",
13154
13405
  summary: "List the requests waiting for you, or answer one: once, always, accept, decline or block",
@@ -13191,7 +13442,7 @@ const CONSENT_COMMANDS = [
13191
13442
  if (values.all === true) throw new UsageError("--all goes with `requests answer`");
13192
13443
  const { requests: held } = await client.call("request.list", {});
13193
13444
  if (ctx.json) {
13194
- ctx.out.json({ requests: held });
13445
+ ctx.out.json({ requests: held.map(({ actions: _actions, ...request }) => request) });
13195
13446
  return;
13196
13447
  }
13197
13448
  if (held.length === 0) {
@@ -14929,6 +15180,12 @@ function conversationEvent(event) {
14929
15180
  type: event.type,
14930
15181
  pos: event.pos
14931
15182
  };
15183
+ case "task": return {
15184
+ type: event.type,
15185
+ task: event.task.task.id,
15186
+ role: event.task.role,
15187
+ state: event.task.task.status.state
15188
+ };
14932
15189
  }
14933
15190
  }
14934
15191
  async function syncConversations(client, ctx, position) {
@@ -16285,6 +16542,7 @@ const SECTIONS = [
16285
16542
  "devices",
16286
16543
  "grants",
16287
16544
  "grant",
16545
+ "reach",
16288
16546
  "requests",
16289
16547
  "contact",
16290
16548
  "card",