agentic-notify 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Notifications for humans and agents: in-app inbox, email and webhook delivery, with a CLI, API, MCP server and SDK.
7
7
 
8
- **Status: 0.4.3.** Breaking for Worker auth, see "Migrating from `NOTIFY_TOKENS`" below. Breaking for 0.1.0 code and databases, see the CHANGELOG upgrade steps. Works today: the notification model, preferences and mute, digest, a store port from agentic-identity with its memory and D1 adapters, signed webhook and email delivery through a dispatcher, an HTTP API in a Worker, an SDK, a CLI, MCP tools, per-recipient export and erase, and a retention sweep. Not done: a real email provider adapter, webhook endpoint management, and a web UI.
8
+ **Status: 0.5.0.** Breaking for Worker auth, see "Migrating from `NOTIFY_TOKENS`" below. Breaking for 0.1.0 code and databases, see the CHANGELOG upgrade steps. Works today: the notification model, preferences and mute, digest, a store port from agentic-identity with its memory and D1 adapters, signed webhook and email delivery through a dispatcher, an HTTP API in a Worker, an SDK, a CLI, MCP tools, per-recipient export and erase, and a retention sweep. Not done: a real email provider adapter, webhook endpoint management, and a web UI.
9
9
 
10
10
  ## Live demo
11
11
 
@@ -122,6 +122,10 @@ Library users: `createWorker` takes `auth` in place of `resolver`. `authorizeSen
122
122
  - Logs hold ids, channel names and error names only. They never hold bodies or addresses.
123
123
  - Erase removes a recipient's own notifications and preferences. Notifications that name the person only as actor stay with their recipients.
124
124
 
125
+ ## Account export and erase
126
+
127
+ A host that runs account export and erase across many packages calls `notifyAccount` from `agentic-notify/account`. It has `exportAccount(subject, { notifier })` and `eraseAccount(subject, { notifier })`, so the host does not read the storage layout. The subject is an id and a kind. A person or a user token is a `human` recipient. Every agent kind is an `agent` recipient. The export has plain JSON in `notifications` and `preferences`. The erase removes both and returns counts. A repeat of the erase counts zero. Notifications that name the subject only as actor stay with their recipients. The shape is provisional: it is the `AccountPackage` contract that a later `agentic-identity` release adds to `agentic-identity/account`.
128
+
125
129
  ## Testing
126
130
 
127
131
  `agentic-notify/testing` helps you test a store adapter and your own code.
@@ -0,0 +1,25 @@
1
+ import { PrincipalKind } from 'agentic-identity';
2
+ import { N as Notifier } from './service-BSoAyGBs.js';
3
+ import './gdpr-C3YxbZp-.js';
4
+ import './types-BAG4ZSoy.js';
5
+ import 'zod';
6
+
7
+ interface NotifyAccountDeps {
8
+ notifier: Notifier;
9
+ }
10
+ /** Who the account is for: an id and a kind. The host takes the kind from the signed-in principal. */
11
+ interface Subject {
12
+ id: string;
13
+ kind: PrincipalKind;
14
+ }
15
+ type JsonRecord = Record<string, unknown>;
16
+ interface NotifyAccount {
17
+ id: "notify";
18
+ /** Collections: `notifications` (every one in the subject's inbox) and `preferences` (the subject's own, one row or none). */
19
+ exportAccount(subject: Subject, deps: NotifyAccountDeps): Promise<Record<"notifications" | "preferences", JsonRecord[]>>;
20
+ /** Erases the subject's notifications and preferences. Counts by `notifications` and `preferences`. A repeat counts zero. */
21
+ eraseAccount(subject: Subject, deps: NotifyAccountDeps): Promise<Record<"notifications" | "preferences", number>>;
22
+ }
23
+ declare const notifyAccount: NotifyAccount;
24
+
25
+ export { type NotifyAccount, type NotifyAccountDeps, type Subject, notifyAccount };
@@ -0,0 +1,7 @@
1
+ import {
2
+ notifyAccount
3
+ } from "./chunk-FAZRZNK5.js";
4
+ import "./chunk-NB5X6GVM.js";
5
+ export {
6
+ notifyAccount
7
+ };
@@ -0,0 +1,48 @@
1
+ import {
2
+ recipientSchema
3
+ } from "./chunk-NB5X6GVM.js";
4
+
5
+ // src/account.ts
6
+ var plain = (value) => JSON.parse(JSON.stringify(value));
7
+ function roleKind(kind) {
8
+ switch (kind) {
9
+ case "human":
10
+ case "user_token":
11
+ return "human";
12
+ case "agent_of_human":
13
+ case "agent_of_agent":
14
+ case "agent":
15
+ return "agent";
16
+ default:
17
+ return void 0;
18
+ }
19
+ }
20
+ function recipientOf(subject) {
21
+ const kind = roleKind(subject?.kind);
22
+ const parsed = recipientSchema.safeParse({ kind, id: subject?.id });
23
+ if (kind === void 0 || !parsed.success || parsed.data.id.trim() === "") throw new TypeError("subject needs an id and a known kind");
24
+ return parsed.data;
25
+ }
26
+ function check(subject, deps) {
27
+ const { notifier } = deps ?? {};
28
+ if (["exportData", "eraseWithCounts"].some((name) => typeof notifier?.[name] !== "function")) {
29
+ throw new TypeError("notifyAccount needs deps.notifier");
30
+ }
31
+ return recipientOf(subject);
32
+ }
33
+ var notifyAccount = {
34
+ id: "notify",
35
+ async exportAccount(subject, deps) {
36
+ const recipient = check(subject, deps);
37
+ const out = await deps.notifier.exportData(recipient);
38
+ return { notifications: plain(out.notifications), preferences: plain(out.preferences ? [out.preferences] : []) };
39
+ },
40
+ async eraseAccount(subject, deps) {
41
+ const recipient = check(subject, deps);
42
+ return deps.notifier.eraseWithCounts(recipient);
43
+ }
44
+ };
45
+
46
+ export {
47
+ notifyAccount
48
+ };
@@ -0,0 +1,54 @@
1
+ // src/core/types.ts
2
+ import { z } from "zod";
3
+ var CHANNELS = ["inbox", "webhook", "email"];
4
+ var id = z.string().min(1).max(200);
5
+ var recipientSchema = z.object({ kind: z.enum(["human", "agent"]), id }).strict();
6
+ var typeNameSchema = z.string().regex(/^[a-z][a-z0-9_.-]{0,63}$/);
7
+ var resourceRefSchema = z.object({
8
+ kind: z.string().min(1).max(100),
9
+ id,
10
+ url: z.string().max(2e3).refine((u) => /^https?:\/\//i.test(u) && URL.canParse(u), "url must be http or https").optional()
11
+ }).strict();
12
+ var actorSchema = z.object({ kind: z.enum(["human", "agent"]), id }).strict();
13
+ var notificationSchema = z.object({
14
+ id,
15
+ recipient: recipientSchema,
16
+ type: typeNameSchema,
17
+ resource: resourceRefSchema,
18
+ actor: actorSchema,
19
+ body: z.string().max(2e3),
20
+ createdAt: z.number().int().nonnegative(),
21
+ readAt: z.number().int().nonnegative().nullable()
22
+ }).strict();
23
+ var sendInputSchema = z.object({
24
+ recipient: recipientSchema,
25
+ type: typeNameSchema,
26
+ resource: resourceRefSchema,
27
+ actor: actorSchema,
28
+ body: z.string().max(2e3)
29
+ }).strict();
30
+ var preferencesSchema = z.object({
31
+ channels: z.record(typeNameSchema, z.array(z.enum(CHANNELS)).max(CHANNELS.length).refine((list) => new Set(list).size === list.length, "channels must not repeat")),
32
+ muted: z.boolean(),
33
+ mutedTypes: z.array(typeNameSchema).max(200)
34
+ }).strict();
35
+ var DEFAULT_CHANNELS = ["inbox"];
36
+ function defaultPreferences() {
37
+ return { channels: {}, muted: false, mutedTypes: [] };
38
+ }
39
+ function recipientKey(recipient) {
40
+ return `${recipient.kind}:${recipient.id}`;
41
+ }
42
+
43
+ export {
44
+ CHANNELS,
45
+ recipientSchema,
46
+ typeNameSchema,
47
+ resourceRefSchema,
48
+ notificationSchema,
49
+ sendInputSchema,
50
+ preferencesSchema,
51
+ DEFAULT_CHANNELS,
52
+ defaultPreferences,
53
+ recipientKey
54
+ };
@@ -1,44 +1,13 @@
1
- // src/core/types.ts
2
- import { z } from "zod";
3
- var CHANNELS = ["inbox", "webhook", "email"];
4
- var id = z.string().min(1).max(200);
5
- var recipientSchema = z.object({ kind: z.enum(["human", "agent"]), id }).strict();
6
- var typeNameSchema = z.string().regex(/^[a-z][a-z0-9_.-]{0,63}$/);
7
- var resourceRefSchema = z.object({
8
- kind: z.string().min(1).max(100),
9
- id,
10
- url: z.string().max(2e3).refine((u) => /^https?:\/\//i.test(u) && URL.canParse(u), "url must be http or https").optional()
11
- }).strict();
12
- var actorSchema = z.object({ kind: z.enum(["human", "agent"]), id }).strict();
13
- var notificationSchema = z.object({
14
- id,
15
- recipient: recipientSchema,
16
- type: typeNameSchema,
17
- resource: resourceRefSchema,
18
- actor: actorSchema,
19
- body: z.string().max(2e3),
20
- createdAt: z.number().int().nonnegative(),
21
- readAt: z.number().int().nonnegative().nullable()
22
- }).strict();
23
- var sendInputSchema = z.object({
24
- recipient: recipientSchema,
25
- type: typeNameSchema,
26
- resource: resourceRefSchema,
27
- actor: actorSchema,
28
- body: z.string().max(2e3)
29
- }).strict();
30
- var preferencesSchema = z.object({
31
- channels: z.record(typeNameSchema, z.array(z.enum(CHANNELS)).max(CHANNELS.length).refine((list) => new Set(list).size === list.length, "channels must not repeat")),
32
- muted: z.boolean(),
33
- mutedTypes: z.array(typeNameSchema).max(200)
34
- }).strict();
35
- var DEFAULT_CHANNELS = ["inbox"];
36
- function defaultPreferences() {
37
- return { channels: {}, muted: false, mutedTypes: [] };
38
- }
39
- function recipientKey(recipient) {
40
- return `${recipient.kind}:${recipient.id}`;
41
- }
1
+ import {
2
+ DEFAULT_CHANNELS,
3
+ defaultPreferences,
4
+ notificationSchema,
5
+ preferencesSchema,
6
+ recipientKey,
7
+ recipientSchema,
8
+ sendInputSchema,
9
+ typeNameSchema
10
+ } from "./chunk-NB5X6GVM.js";
42
11
 
43
12
  // src/core/gdpr.ts
44
13
  var NOTES = "notifications";
@@ -48,7 +17,7 @@ async function deleteAll(store, ids) {
48
17
  for (let i = 0; i < ids.length; i += DELETE_BATCH) {
49
18
  const batch = ids.slice(i, i + DELETE_BATCH);
50
19
  await store.transaction(async (tx) => {
51
- for (const id2 of batch) await tx.delete(NOTES, id2);
20
+ for (const id of batch) await tx.delete(NOTES, id);
52
21
  });
53
22
  }
54
23
  }
@@ -77,6 +46,9 @@ async function exportRecipient(store, recipient) {
77
46
  return { recipient, preferences: prefs ? preferencesSchema.parse(prefs) : null, notifications };
78
47
  }
79
48
  async function eraseRecipient(store, recipient) {
49
+ return (await eraseRecipientCounts(store, recipient)).notifications;
50
+ }
51
+ async function eraseRecipientCounts(store, recipient) {
80
52
  let removed = 0;
81
53
  for (let pass = 0; ; pass++) {
82
54
  if (pass >= 20) throw new Error("erase did not finish: deletes had no effect");
@@ -86,8 +58,13 @@ async function eraseRecipient(store, recipient) {
86
58
  await deleteAll(store, ids);
87
59
  removed += ids.length;
88
60
  }
89
- await store.delete(PREFS, recipientKey(recipient));
90
- return removed;
61
+ const key = recipientKey(recipient);
62
+ const preferences = await store.transaction(async (tx) => {
63
+ const held = await tx.get(PREFS, key) ? 1 : 0;
64
+ await tx.delete(PREFS, key);
65
+ return held;
66
+ });
67
+ return { notifications: removed, preferences };
91
68
  }
92
69
  async function sweepBefore(store, cutoff) {
93
70
  if (!Number.isFinite(cutoff)) throw new RangeError("cutoff must be a finite number");
@@ -108,7 +85,7 @@ async function sweepBefore(store, cutoff) {
108
85
  }
109
86
 
110
87
  // src/core/service.ts
111
- import { z as z2 } from "zod";
88
+ import { z } from "zod";
112
89
  var NotFoundError = class extends Error {
113
90
  code = "NOT_FOUND";
114
91
  constructor(message = "notification not found") {
@@ -196,22 +173,22 @@ function createNotifier(options) {
196
173
  if (!doc || doc.recipientKey !== recipientKey(recipient)) throw new NotFoundError();
197
174
  return doc;
198
175
  }
199
- async function get(recipient, id2) {
176
+ async function get(recipient, id) {
200
177
  const r = recipientSchema.parse(recipient);
201
- return fromDoc(check(await store.get(NOTES, id2), r));
178
+ return fromDoc(check(await store.get(NOTES, id), r));
202
179
  }
203
- async function markReadOnce(recipient, id2) {
180
+ async function markReadOnce(recipient, id) {
204
181
  const r = recipientSchema.parse(recipient);
205
182
  return store.transaction(async (tx) => {
206
- const n = fromDoc(check(await tx.get(NOTES, id2), r));
183
+ const n = fromDoc(check(await tx.get(NOTES, id), r));
207
184
  if (n.readAt !== null) return { notification: n, won: false };
208
185
  const next = notificationSchema.parse({ ...n, readAt: now() });
209
- await tx.put(NOTES, id2, toDoc(next));
186
+ await tx.put(NOTES, id, toDoc(next));
210
187
  return { notification: next, won: true };
211
188
  });
212
189
  }
213
- async function markRead(recipient, id2) {
214
- return (await markReadOnce(recipient, id2)).notification;
190
+ async function markRead(recipient, id) {
191
+ return (await markReadOnce(recipient, id)).notification;
215
192
  }
216
193
  async function markAllRead(recipient) {
217
194
  let count = 0;
@@ -237,7 +214,7 @@ function createNotifier(options) {
237
214
  return count;
238
215
  }
239
216
  async function digest(recipient, since = 0) {
240
- since = z2.number().int().nonnegative().parse(since);
217
+ since = z.number().int().nonnegative().parse(since);
241
218
  const groups = /* @__PURE__ */ new Map();
242
219
  let total = 0;
243
220
  let cursor;
@@ -263,6 +240,9 @@ function createNotifier(options) {
263
240
  async function erase(recipient) {
264
241
  return { notifications: await eraseRecipient(store, recipientSchema.parse(recipient)) };
265
242
  }
243
+ async function eraseWithCounts(recipient) {
244
+ return eraseRecipientCounts(store, recipientSchema.parse(recipient));
245
+ }
266
246
  async function sweep() {
267
247
  if (options.retentionMs === void 0) return 0;
268
248
  return sweepBefore(store, now() - options.retentionMs);
@@ -283,19 +263,12 @@ function createNotifier(options) {
283
263
  parseType,
284
264
  exportData,
285
265
  erase,
266
+ eraseWithCounts,
286
267
  sweep
287
268
  };
288
269
  }
289
270
 
290
271
  export {
291
- CHANNELS,
292
- recipientSchema,
293
- typeNameSchema,
294
- resourceRefSchema,
295
- preferencesSchema,
296
- DEFAULT_CHANNELS,
297
- defaultPreferences,
298
- recipientKey,
299
272
  NOTES,
300
273
  NotFoundError,
301
274
  createNotifier
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "agentic-notify",
4
- version: "0.4.3",
4
+ version: "0.5.0",
5
5
  description: "Notifications for humans and agents: in-app inbox, webhook and email delivery, with SDK, CLI, MCP server and Worker API.",
6
6
  keywords: [
7
7
  "notifications",
@@ -46,6 +46,10 @@ var package_default = {
46
46
  types: "./dist/sdk.d.ts",
47
47
  import: "./dist/sdk.js"
48
48
  },
49
+ "./account": {
50
+ types: "./dist/account.d.ts",
51
+ import: "./dist/account.js"
52
+ },
49
53
  "./worker": {
50
54
  types: "./dist/worker.d.ts",
51
55
  import: "./dist/worker.js"
package/dist/cli.js CHANGED
@@ -1,16 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  PACKAGE_NAME
4
- } from "./chunk-3N77SYRA.js";
4
+ } from "./chunk-LPZHRY6R.js";
5
+ import "./chunk-FAZRZNK5.js";
5
6
  import {
6
7
  ApiError,
7
8
  createClient
8
9
  } from "./chunk-FJPEUDTG.js";
9
10
  import "./chunk-KJKM56FT.js";
10
- import "./chunk-ARL7FN6Y.js";
11
+ import "./chunk-RRHLT4QA.js";
12
+ import "./chunk-NB5X6GVM.js";
11
13
  import {
12
14
  VERSION
13
- } from "./chunk-4Y6IF3LE.js";
15
+ } from "./chunk-YTUVMIJK.js";
14
16
 
15
17
  // src/cli.ts
16
18
  import { realpathSync } from "fs";
@@ -0,0 +1,28 @@
1
+ import { N as Notifier } from './service-BSoAyGBs.js';
2
+ import { N as Notification, C as Channel, S as SendInput } from './types-BAG4ZSoy.js';
3
+ import { D as DeliveryChannel, L as Logger } from './types-DhgcIImw.js';
4
+
5
+ interface DispatchResult {
6
+ notification: Notification | null;
7
+ stored: boolean;
8
+ muted: boolean;
9
+ /** `skipped` means nothing was sent: the recipient has no target, or no channel is set up for it. */
10
+ deliveries: {
11
+ channel: Channel;
12
+ ok: boolean;
13
+ error?: string;
14
+ skipped?: "no_target" | "no_channel";
15
+ }[];
16
+ }
17
+ interface DispatcherOptions {
18
+ notifier: Notifier;
19
+ /** Channels other than the inbox. A channel with no entry is skipped. */
20
+ channels: Partial<Record<Exclude<Channel, "inbox">, DeliveryChannel>>;
21
+ logger?: Logger;
22
+ }
23
+ declare function createDispatcher(options: DispatcherOptions): {
24
+ /** Store in the inbox, then try each other channel the recipient chose. One failure never blocks the rest. */
25
+ notify(input: SendInput): Promise<DispatchResult>;
26
+ };
27
+
28
+ export { type DispatchResult as D, type DispatcherOptions as a, createDispatcher as c };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,14 @@
1
- export { D as DispatchResult, a as DispatcherOptions, L as ListOptions, b as ListResult, d as NotFoundError, N as Notifier, e as NotifierOptions, S as SendResult, c as createDispatcher, f as createNotifier } from './dispatch-CH4Ju-_1.js';
1
+ export { L as ListOptions, a as ListResult, b as NotFoundError, N as Notifier, c as NotifierOptions, S as SendResult, d as createNotifier } from './service-BSoAyGBs.js';
2
2
  export { Doc, Page, Query, Scalar, Store, StoreOps, createMemoryStore } from 'agentic-identity';
3
3
  import { R as Recipient } from './types-BAG4ZSoy.js';
4
4
  export { A as Actor, b as CHANNELS, C as Channel, c as DEFAULT_CHANNELS, D as Digest, d as DigestGroup, N as Notification, P as Preferences, a as ResourceRef, S as SendInput, e as defaultPreferences, r as recipientKey } from './types-BAG4ZSoy.js';
5
+ export { D as DispatchResult, a as DispatcherOptions, c as createDispatcher } from './dispatch-DDo1_Ods.js';
5
6
  import { D as DeliveryChannel } from './types-DhgcIImw.js';
6
7
  export { a as DeliveryError, L as Logger } from './types-DhgcIImw.js';
7
8
  export { E as EmailChannelOptions, a as EmailMessage, b as EmailPort, c as createEmailChannel } from './testing-DEBqTQFK.js';
8
9
  export { D1Like, D1_SCHEMA, createD1Store } from 'agentic-identity/cloudflare';
9
10
  export { R as RecipientExport } from './gdpr-C3YxbZp-.js';
11
+ export { Subject as AccountSubject, NotifyAccount, NotifyAccountDeps, notifyAccount } from './account.js';
10
12
  import 'zod';
11
13
  import 'agentic-identity/testing';
12
14
 
package/dist/index.js CHANGED
@@ -9,21 +9,26 @@ import {
9
9
  createWebhookChannel,
10
10
  signPayload,
11
11
  verifySignature
12
- } from "./chunk-3N77SYRA.js";
12
+ } from "./chunk-LPZHRY6R.js";
13
+ import {
14
+ notifyAccount
15
+ } from "./chunk-FAZRZNK5.js";
13
16
  import {
14
17
  createEmailChannel
15
18
  } from "./chunk-KJKM56FT.js";
19
+ import {
20
+ NotFoundError,
21
+ createNotifier
22
+ } from "./chunk-RRHLT4QA.js";
16
23
  import {
17
24
  CHANNELS,
18
25
  DEFAULT_CHANNELS,
19
- NotFoundError,
20
- createNotifier,
21
26
  defaultPreferences,
22
27
  recipientKey
23
- } from "./chunk-ARL7FN6Y.js";
28
+ } from "./chunk-NB5X6GVM.js";
24
29
  import {
25
30
  VERSION
26
- } from "./chunk-4Y6IF3LE.js";
31
+ } from "./chunk-YTUVMIJK.js";
27
32
  export {
28
33
  CHANNELS,
29
34
  D1_SCHEMA,
@@ -40,6 +45,7 @@ export {
40
45
  createNotifier,
41
46
  createWebhookChannel,
42
47
  defaultPreferences,
48
+ notifyAccount,
43
49
  recipientKey,
44
50
  signPayload,
45
51
  verifySignature
package/dist/mcp-bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  VERSION
4
- } from "./chunk-4Y6IF3LE.js";
4
+ } from "./chunk-YTUVMIJK.js";
5
5
 
6
6
  // src/mcp-bin.ts
7
7
  var HELP = `agentic-notify-mcp ${VERSION}
package/dist/mcp.js CHANGED
@@ -1,19 +1,21 @@
1
1
  import {
2
2
  PACKAGE_NAME
3
- } from "./chunk-3N77SYRA.js";
3
+ } from "./chunk-LPZHRY6R.js";
4
+ import "./chunk-FAZRZNK5.js";
4
5
  import {
5
6
  ApiError
6
7
  } from "./chunk-FJPEUDTG.js";
7
8
  import "./chunk-KJKM56FT.js";
9
+ import "./chunk-RRHLT4QA.js";
8
10
  import {
9
11
  preferencesSchema,
10
12
  recipientSchema,
11
13
  resourceRefSchema,
12
14
  typeNameSchema
13
- } from "./chunk-ARL7FN6Y.js";
15
+ } from "./chunk-NB5X6GVM.js";
14
16
  import {
15
17
  VERSION
16
- } from "./chunk-4Y6IF3LE.js";
18
+ } from "./chunk-YTUVMIJK.js";
17
19
 
18
20
  // src/mcp.ts
19
21
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -1,7 +1,6 @@
1
1
  import { R as RecipientExport } from './gdpr-C3YxbZp-.js';
2
2
  import { Store } from 'agentic-identity';
3
3
  import { S as SendInput, N as Notification, C as Channel, R as Recipient, D as Digest, P as Preferences } from './types-BAG4ZSoy.js';
4
- import { D as DeliveryChannel, L as Logger } from './types-DhgcIImw.js';
5
4
 
6
5
  interface NotifierOptions {
7
6
  store: Store;
@@ -47,31 +46,12 @@ declare function createNotifier(options: NotifierOptions): {
47
46
  erase: (recipient: Recipient) => Promise<{
48
47
  notifications: number;
49
48
  }>;
49
+ eraseWithCounts: (recipient: Recipient) => Promise<{
50
+ notifications: number;
51
+ preferences: number;
52
+ }>;
50
53
  sweep: () => Promise<number>;
51
54
  };
52
55
  type Notifier = ReturnType<typeof createNotifier>;
53
56
 
54
- interface DispatchResult {
55
- notification: Notification | null;
56
- stored: boolean;
57
- muted: boolean;
58
- /** `skipped` means nothing was sent: the recipient has no target, or no channel is set up for it. */
59
- deliveries: {
60
- channel: Channel;
61
- ok: boolean;
62
- error?: string;
63
- skipped?: "no_target" | "no_channel";
64
- }[];
65
- }
66
- interface DispatcherOptions {
67
- notifier: Notifier;
68
- /** Channels other than the inbox. A channel with no entry is skipped. */
69
- channels: Partial<Record<Exclude<Channel, "inbox">, DeliveryChannel>>;
70
- logger?: Logger;
71
- }
72
- declare function createDispatcher(options: DispatcherOptions): {
73
- /** Store in the inbox, then try each other channel the recipient chose. One failure never blocks the rest. */
74
- notify(input: SendInput): Promise<DispatchResult>;
75
- };
76
-
77
- export { type DispatchResult as D, type ListOptions as L, type Notifier as N, type SendResult as S, type DispatcherOptions as a, type ListResult as b, createDispatcher as c, NotFoundError as d, type NotifierOptions as e, createNotifier as f };
57
+ export { type ListOptions as L, type Notifier as N, type SendResult as S, type ListResult as a, NotFoundError as b, type NotifierOptions as c, createNotifier as d };
package/dist/worker.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import { Auth, PrincipalContext, Store } from 'agentic-identity';
2
- import { N as Notifier, c as createDispatcher } from './dispatch-CH4Ju-_1.js';
2
+ import { N as Notifier } from './service-BSoAyGBs.js';
3
3
  import { R as Recipient } from './types-BAG4ZSoy.js';
4
+ import { c as createDispatcher } from './dispatch-DDo1_Ods.js';
4
5
  import { D1Like } from 'agentic-identity/cloudflare';
5
6
  import './gdpr-C3YxbZp-.js';
6
- import './types-DhgcIImw.js';
7
7
  import 'zod';
8
+ import './types-DhgcIImw.js';
8
9
 
9
10
  interface AppOptions {
10
11
  notifier: Notifier;
package/dist/worker.js CHANGED
@@ -1,15 +1,17 @@
1
1
  import {
2
2
  NOTES,
3
3
  NotFoundError,
4
- createNotifier,
4
+ createNotifier
5
+ } from "./chunk-RRHLT4QA.js";
6
+ import {
5
7
  preferencesSchema,
6
8
  recipientSchema,
7
9
  resourceRefSchema,
8
10
  typeNameSchema
9
- } from "./chunk-ARL7FN6Y.js";
11
+ } from "./chunk-NB5X6GVM.js";
10
12
  import {
11
13
  VERSION
12
- } from "./chunk-4Y6IF3LE.js";
14
+ } from "./chunk-YTUVMIJK.js";
13
15
 
14
16
  // src/api.ts
15
17
  import { Hono } from "hono";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-notify",
3
- "version": "0.4.3",
3
+ "version": "0.5.0",
4
4
  "description": "Notifications for humans and agents: in-app inbox, webhook and email delivery, with SDK, CLI, MCP server and Worker API.",
5
5
  "keywords": [
6
6
  "notifications",
@@ -45,6 +45,10 @@
45
45
  "types": "./dist/sdk.d.ts",
46
46
  "import": "./dist/sdk.js"
47
47
  },
48
+ "./account": {
49
+ "types": "./dist/account.d.ts",
50
+ "import": "./dist/account.js"
51
+ },
48
52
  "./worker": {
49
53
  "types": "./dist/worker.d.ts",
50
54
  "import": "./dist/worker.js"
File without changes