@kehto/services 0.12.3 → 0.13.2
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 +25 -2
- package/dist/index.d.ts +378 -11
- package/dist/index.js +897 -100
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @kehto/services
|
|
2
2
|
|
|
3
|
-
Reference service handlers for the napplet protocol — audio, notifications, identity, relay pool, cache, keys, media, notify, theme, link, common, lists, serial, BLE, WebRTC.
|
|
3
|
+
Reference service handlers for the napplet protocol — audio, notifications, identity, relay pool, cache, keys, media, notify, theme, link, common, lists, serial, BLE, WebRTC, DM.
|
|
4
4
|
|
|
5
5
|
> **Alpha status:** Kehto is an early runtime implementation for a draft NIP-5D
|
|
6
6
|
> protocol. NAP contracts and service envelopes are not final; treat these
|
|
@@ -23,7 +23,11 @@ Current draft posture:
|
|
|
23
23
|
- The v1.1 signer service is deleted outright. Its responsibilities split into two: read-only identity lookups go through `createIdentityService` (`getPublicKey`, `getRelays`, `getProfile`, `getFollows`, `getList`, `getZaps`, `getMutes`, `getBlocked`, `getBadges`); signing happens inside the shell as part of `relay.publish` / `relay.publishEncrypted` and is never exposed to napplets.
|
|
24
24
|
- `createKeysService` and `createMediaService` ship real reference backends as of v1.4 (see the dedicated sections below). `createKeysService` attaches a document-level `keydown` listener by default and delivers `keys.action` push envelopes to registered napplets; `createMediaService` mirrors session metadata and playback state to `navigator.mediaSession` and emits `media.command` push envelopes on OS transport events. Both accept a host-bridge option (`HostKeysBridge` / `HostMediaBridge`) so Electron / Tauri / native shells can swap in OS-level backends without re-implementing the wire-protocol bookkeeping.
|
|
25
25
|
- `createNotifyService` (NIP-5D `notify.*` NAP) coexists with the legacy `createNotificationService` (inc-emit `notifications:*` channel). Both may be registered simultaneously while hosts migrate.
|
|
26
|
+
- `createOutboxService` supports `outbox.getEvent` from draft NAP-OUTBOX. Single-event lookups run through shell-owned relay routing and only return events whose ID matches the request.
|
|
26
27
|
- `createResourceService` supports `resource.bytesMany` from draft NAP-RESOURCE. Bulk requests return ordered per-URL items and keep per-URL failures local while preserving legacy single-fetch fields for existing Kehto callers.
|
|
28
|
+
- `createUploadService` supports `upload.info` from draft NAP-UPLOAD. Hosts may expose configured rails, return URL forms, maximum bytes, and MIME type policy without requiring napplets to start an upload.
|
|
29
|
+
- `createResourceService` supports `resource.info` and `resource.bytesMany` from draft NAP-RESOURCE. `resource.info` returns advisory schemes and coarse limits; bulk requests return ordered per-URL items and keep per-URL failures local while preserving legacy single-fetch fields for existing Kehto callers.
|
|
30
|
+
- `createDmService` keeps NAP-DM request correlation, subscriptions, and message normalization in runtime-owned code. Adapters cover concrete transports: NIP-17 gift wraps via `nostr-tools`, structural NDR runtimes with relay hooks, and Cordn/ContextVM coordinator clients. Kehto mirrors NAP-DM wire types locally until `@napplet/core` / `@napplet/nap` publish them.
|
|
27
31
|
|
|
28
32
|
## Quick Start
|
|
29
33
|
|
|
@@ -33,6 +37,8 @@ import {
|
|
|
33
37
|
createListsService,
|
|
34
38
|
createNotificationService,
|
|
35
39
|
createBleService,
|
|
40
|
+
createDmService,
|
|
41
|
+
createNip17DmAdapter,
|
|
36
42
|
createSerialService,
|
|
37
43
|
createWebrtcService,
|
|
38
44
|
} from '@kehto/services';
|
|
@@ -64,6 +70,17 @@ runtime.registerService(
|
|
|
64
70
|
);
|
|
65
71
|
|
|
66
72
|
// Serial service — runtime-owned serial sessions and host-owned device access.
|
|
73
|
+
runtime.registerService(
|
|
74
|
+
'dm',
|
|
75
|
+
createDmService({
|
|
76
|
+
adapter: createNip17DmAdapter({
|
|
77
|
+
ownerSecretKey: shellOwnedSecretKey,
|
|
78
|
+
relayPool: shellRelayPool,
|
|
79
|
+
relays: ['wss://relay.example'],
|
|
80
|
+
}),
|
|
81
|
+
}),
|
|
82
|
+
);
|
|
83
|
+
|
|
67
84
|
runtime.registerService(
|
|
68
85
|
'serial',
|
|
69
86
|
createSerialService({
|
|
@@ -447,6 +464,12 @@ Each factory returns a `ServiceHandler` registrable via `runtime.registerService
|
|
|
447
464
|
### WebRTC NAP
|
|
448
465
|
- `createWebrtcService` — `webrtc.open`, `webrtc.send`, `webrtc.close` + host-pushed `webrtc.event` envelopes. The reference handler owns only the NAP request/result bookkeeping; host bridges own signaling, SDP, ICE, peer connection lifecycle, and policy.
|
|
449
466
|
|
|
467
|
+
### DM NAP
|
|
468
|
+
- `createDmService` — `dm.status`, `dm.conversations`, `dm.messages`, `dm.send`, `dm.subscribe`, `dm.unsubscribe` + `dm.message` push envelopes (`dm:read` / `dm:write`). Runtime owns correlation, subscriptions, cleanup, and normalized message shape; adapters own protocol transport.
|
|
469
|
+
- `createNip17DmAdapter` — concrete NIP-17 gift-wrap adapter backed by `nostr-tools/nip17` and an injected relay pool. The owner secret key stays shell/runtime-owned.
|
|
470
|
+
- `createNdrDmAdapter` / `createNdrRelayTransport` — structural adapter for Nostr Double Ratchet runtimes plus a relay transport bridge for app-owned `nostrSubscribe` / `nostrFetch` / `nostrPublish` hooks.
|
|
471
|
+
- `createCordnDmAdapter` / `createCordnRelayCoordinatorClient` — structural adapter for Cordn/ContextVM clients plus a relay-backed coordinator bridge for `PostGroupMessage`, `FetchGroupMessages`, and `SubscribeGroupMessages`.
|
|
472
|
+
|
|
450
473
|
### Theme NAP
|
|
451
474
|
- `createThemeService` — `theme.get` + `theme.changed` fan-out (`theme:read`). Returns a `ThemeService` with `publishTheme()` / `setTheme()` utilities for host-side updates.
|
|
452
475
|
|
|
@@ -454,7 +477,7 @@ Each factory returns a `ServiceHandler` registrable via `runtime.registerService
|
|
|
454
477
|
- `createAudioService` — `audio:*` inc-emit topic handler. Browser-agnostic registry of per-window audio sources; host wires `onChange` to update transport UI.
|
|
455
478
|
|
|
456
479
|
### Types
|
|
457
|
-
`AudioSource`, `AudioServiceOptions`, `Notification`, `NotificationServiceOptions`, `IdentityServiceOptions`, `RelayPoolServiceOptions`, `CacheServiceOptions`, `CoordinatedRelayOptions`, `KeysServiceOptions`, `MediaServiceOptions`, `NotifyServiceOptions`, `ThemeServiceOptions`, `ThemeService`, `BleServiceOptions`, `BleServiceContext`, `WebrtcServiceOptions`, `WebrtcServiceContext`.
|
|
480
|
+
`AudioSource`, `AudioServiceOptions`, `Notification`, `NotificationServiceOptions`, `IdentityServiceOptions`, `RelayPoolServiceOptions`, `CacheServiceOptions`, `CoordinatedRelayOptions`, `KeysServiceOptions`, `MediaServiceOptions`, `NotifyServiceOptions`, `ThemeServiceOptions`, `ThemeService`, `BleServiceOptions`, `BleServiceContext`, `WebrtcServiceOptions`, `WebrtcServiceContext`, `DmServiceOptions`, `DmAdapter`, `DmRelayPool`, `Nip17DmAdapterOptions`, `NdrDmAdapterOptions`, `CordnDmAdapterOptions`.
|
|
458
481
|
|
|
459
482
|
## API Reference
|
|
460
483
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1409,8 +1409,9 @@ declare function createConfigService(options: ConfigServiceOptions): ConfigServi
|
|
|
1409
1409
|
* model per PROJECT.md Decision #31. Kehto keeps legacy single-fetch fields
|
|
1410
1410
|
* for existing callers and also emits the current NAP-RESOURCE fields.
|
|
1411
1411
|
* Handles:
|
|
1412
|
-
* Inbound: resource.bytes, resource.bytesMany, resource.cancel
|
|
1413
|
-
* Outbound: resource.
|
|
1412
|
+
* Inbound: resource.info, resource.bytes, resource.bytesMany, resource.cancel
|
|
1413
|
+
* Outbound: resource.info.result, resource.info.error,
|
|
1414
|
+
* resource.bytes.result, resource.bytes.error,
|
|
1414
1415
|
* resource.bytesMany.result, resource.bytesMany.error
|
|
1415
1416
|
*
|
|
1416
1417
|
* ──────────────────────── SCOPE BOUNDARY (RESOURCE-01) ────────────────────────
|
|
@@ -1445,6 +1446,27 @@ declare function createConfigService(options: ConfigServiceOptions): ConfigServi
|
|
|
1445
1446
|
* ```
|
|
1446
1447
|
*/
|
|
1447
1448
|
|
|
1449
|
+
/** Runtime-disclosed support for one resource URL scheme. */
|
|
1450
|
+
interface ResourceSchemeInfo {
|
|
1451
|
+
scheme: string;
|
|
1452
|
+
enabled: boolean;
|
|
1453
|
+
}
|
|
1454
|
+
/** Advisory resource capability and policy limits disclosed by the runtime. */
|
|
1455
|
+
interface ResourceInfo {
|
|
1456
|
+
schemes: ResourceSchemeInfo[];
|
|
1457
|
+
maxBytes?: number;
|
|
1458
|
+
maxUrls?: number;
|
|
1459
|
+
}
|
|
1460
|
+
/** Context passed to a host-provided resource info resolver. */
|
|
1461
|
+
interface ResourceInfoContext {
|
|
1462
|
+
windowId: string;
|
|
1463
|
+
identity: {
|
|
1464
|
+
dTag: string;
|
|
1465
|
+
aggregateHash: string;
|
|
1466
|
+
} | null;
|
|
1467
|
+
}
|
|
1468
|
+
/** Static or dynamic advisory resource info exposed through `resource.info`. */
|
|
1469
|
+
type ResourceInfoProvider = ResourceInfo | ((context: ResourceInfoContext) => ResourceInfo | Promise<ResourceInfo>);
|
|
1448
1470
|
/**
|
|
1449
1471
|
* Options for `createResourceService` (options-as-bridge per v1.6 Decision 18).
|
|
1450
1472
|
*
|
|
@@ -1509,6 +1531,14 @@ interface ResourceServiceOptions {
|
|
|
1509
1531
|
dTag: string;
|
|
1510
1532
|
aggregateHash: string;
|
|
1511
1533
|
} | null;
|
|
1534
|
+
/**
|
|
1535
|
+
* Advisory NAP-RESOURCE introspection exposed through `resource.info`.
|
|
1536
|
+
*
|
|
1537
|
+
* Provide a static snapshot or a resolver when the shell wants to disclose
|
|
1538
|
+
* configured schemes and coarse limits. Omit to expose the reference
|
|
1539
|
+
* service's conservative default (`https` enabled, no numeric limits).
|
|
1540
|
+
*/
|
|
1541
|
+
resourceInfo?: ResourceInfoProvider;
|
|
1512
1542
|
}
|
|
1513
1543
|
/**
|
|
1514
1544
|
* Type alias for the ServiceHandler returned by `createResourceService`.
|
|
@@ -1518,8 +1548,9 @@ type ResourceService = ServiceHandler;
|
|
|
1518
1548
|
/**
|
|
1519
1549
|
* Create a NAP-RESOURCE reference service.
|
|
1520
1550
|
*
|
|
1521
|
-
* Implements the NAP-RESOURCE request/response protocol: `resource.
|
|
1522
|
-
* `resource.bytesMany`, `resource.cancel`, and their
|
|
1551
|
+
* Implements the NAP-RESOURCE request/response protocol: `resource.info`,
|
|
1552
|
+
* `resource.bytes`, `resource.bytesMany`, `resource.cancel`, and their
|
|
1553
|
+
* result/error envelopes.
|
|
1523
1554
|
*
|
|
1524
1555
|
* On-construction guard (H-03 prevention): all four options are validated at
|
|
1525
1556
|
* factory call time. If any is missing, the factory throws immediately with a
|
|
@@ -1561,10 +1592,11 @@ declare function createResourceService(options: ResourceServiceOptions): Resourc
|
|
|
1561
1592
|
* ships alongside as {@link createRelayPoolOutboxRouter}.
|
|
1562
1593
|
*
|
|
1563
1594
|
* ──────────────────────────── Responsibilities ────────────────────────────
|
|
1564
|
-
* Inbound: outbox.
|
|
1565
|
-
* outbox.resolveRelays
|
|
1566
|
-
* Outbound: outbox.
|
|
1567
|
-
* outbox.
|
|
1595
|
+
* Inbound: outbox.getEvent, outbox.query, outbox.subscribe, outbox.close,
|
|
1596
|
+
* outbox.publish, outbox.resolveRelays
|
|
1597
|
+
* Outbound: outbox.getEvent.result, outbox.query.result, outbox.event,
|
|
1598
|
+
* outbox.eose, outbox.closed, outbox.publish.result,
|
|
1599
|
+
* outbox.resolveRelays.result
|
|
1568
1600
|
*
|
|
1569
1601
|
* The shell owns relay discovery, routing, fallback, deduplication, signature
|
|
1570
1602
|
* validation, signing, and publish fanout policy — all of which live behind
|
|
@@ -1588,6 +1620,17 @@ declare function createResourceService(options: ResourceServiceOptions): Resourc
|
|
|
1588
1620
|
* - `auto` — let the shell choose per its policy and relay intelligence
|
|
1589
1621
|
*/
|
|
1590
1622
|
type OutboxStrategy = 'outbox' | 'inbox' | 'auto';
|
|
1623
|
+
/** Options for a single-event outbox lookup. */
|
|
1624
|
+
interface OutboxEventOptions {
|
|
1625
|
+
/** Author hint for routing through the author's outbox relays. */
|
|
1626
|
+
author?: string;
|
|
1627
|
+
/** Relay hints; treated as a hint subject to shell validation, not a bypass. */
|
|
1628
|
+
relays?: string[];
|
|
1629
|
+
/** Relay-selection strategy. */
|
|
1630
|
+
strategy?: OutboxStrategy;
|
|
1631
|
+
/** Wall-clock budget for the lookup, in milliseconds. */
|
|
1632
|
+
timeoutMs?: number;
|
|
1633
|
+
}
|
|
1591
1634
|
/** Options for a one-shot outbox query. */
|
|
1592
1635
|
interface OutboxQueryOptions {
|
|
1593
1636
|
/** Explicit author hints (augment/override authors derived from filters). */
|
|
@@ -1635,6 +1678,17 @@ interface OutboxRelayPlan {
|
|
|
1635
1678
|
/** Authors for which no relay list could be resolved. */
|
|
1636
1679
|
missingAuthors?: string[];
|
|
1637
1680
|
}
|
|
1681
|
+
/** Outcome of a single-event outbox lookup. */
|
|
1682
|
+
interface OutboxEventResult {
|
|
1683
|
+
/** The signature-validated event matching the requested event id, when found. */
|
|
1684
|
+
event?: NostrEvent;
|
|
1685
|
+
/** Relay URLs where the shell observed the event. */
|
|
1686
|
+
relays: string[];
|
|
1687
|
+
/** True when some relay lists or connections failed and the lookup was partial. */
|
|
1688
|
+
incomplete?: boolean;
|
|
1689
|
+
/** Error reason when the lookup could not complete or did not find the event. */
|
|
1690
|
+
error?: string;
|
|
1691
|
+
}
|
|
1638
1692
|
/** Outcome of an outbox query, as returned by the {@link OutboxRouter}. */
|
|
1639
1693
|
interface OutboxResult {
|
|
1640
1694
|
/** Deduplicated, signature-validated events. */
|
|
@@ -1679,6 +1733,8 @@ interface OutboxRouterSubscription {
|
|
|
1679
1733
|
* fanout. The service translates wire envelopes into these calls and back.
|
|
1680
1734
|
*/
|
|
1681
1735
|
interface OutboxRouter {
|
|
1736
|
+
/** Fetch and validate one event by id through shell-owned outbox routing. */
|
|
1737
|
+
getEvent?(eventId: string, options?: OutboxEventOptions): Promise<OutboxEventResult>;
|
|
1682
1738
|
/** Resolve relays, query them, dedup by id, validate signatures, collect events. */
|
|
1683
1739
|
query(filters: NostrFilter[], options?: OutboxQueryOptions): Promise<OutboxResult>;
|
|
1684
1740
|
/** Open a live outbox-aware subscription, streaming through `sink`. */
|
|
@@ -1827,8 +1883,9 @@ declare function createRelayPoolOutboxRouter(options: RelayPoolOutboxRouterOptio
|
|
|
1827
1883
|
* {@link createHttpUploader}.
|
|
1828
1884
|
*
|
|
1829
1885
|
* ──────────────────────────── Responsibilities ────────────────────────────
|
|
1830
|
-
* Inbound: upload.upload, upload.status
|
|
1831
|
-
* Outbound: upload.
|
|
1886
|
+
* Inbound: upload.info, upload.upload, upload.status
|
|
1887
|
+
* Outbound: upload.info.result, upload.upload.result,
|
|
1888
|
+
* upload.status.result, upload.status.changed
|
|
1832
1889
|
*
|
|
1833
1890
|
* The service owns the `uploadId` (generated per request, scoped to the
|
|
1834
1891
|
* requesting napplet), tracks the latest {@link UploadStatus} per upload for
|
|
@@ -1922,6 +1979,24 @@ interface UploadStatus extends UploadResult {
|
|
|
1922
1979
|
/** Unix ms timestamp of this status. */
|
|
1923
1980
|
updatedAt: number;
|
|
1924
1981
|
}
|
|
1982
|
+
/** Runtime-disclosed support for one upload rail. */
|
|
1983
|
+
interface UploadRailInfo {
|
|
1984
|
+
rail: UploadRail;
|
|
1985
|
+
enabled: boolean;
|
|
1986
|
+
returns?: string[];
|
|
1987
|
+
}
|
|
1988
|
+
/** Advisory upload rails and coarse policy limits disclosed by the runtime. */
|
|
1989
|
+
interface UploadInfo {
|
|
1990
|
+
rails: UploadRailInfo[];
|
|
1991
|
+
maxBytes?: number;
|
|
1992
|
+
mimeTypes?: string[];
|
|
1993
|
+
}
|
|
1994
|
+
/** Context passed to a host-provided upload info resolver. */
|
|
1995
|
+
interface UploadInfoContext {
|
|
1996
|
+
windowId: string;
|
|
1997
|
+
}
|
|
1998
|
+
/** Static or dynamic advisory upload info exposed through `upload.info`. */
|
|
1999
|
+
type UploadInfoProvider = UploadInfo | ((context: UploadInfoContext) => UploadInfo | Promise<UploadInfo>);
|
|
1925
2000
|
/**
|
|
1926
2001
|
* Context handed to an {@link Uploader} for a single upload. Carries the
|
|
1927
2002
|
* service-owned `uploadId` and a sink for streaming progress / state changes.
|
|
@@ -1957,6 +2032,13 @@ interface Uploader {
|
|
|
1957
2032
|
interface UploadServiceOptions {
|
|
1958
2033
|
/** The upload backend the shell uses. Required. */
|
|
1959
2034
|
uploader: Uploader;
|
|
2035
|
+
/**
|
|
2036
|
+
* Advisory NAP-UPLOAD introspection exposed through `upload.info`.
|
|
2037
|
+
*
|
|
2038
|
+
* Provide a static snapshot or resolver when the shell wants to disclose
|
|
2039
|
+
* configured rails and coarse limits. Omit to expose no rails and no limits.
|
|
2040
|
+
*/
|
|
2041
|
+
uploadInfo?: UploadInfoProvider;
|
|
1960
2042
|
/** Generate an upload id; defaults to `crypto.randomUUID()`. */
|
|
1961
2043
|
generateId?: () => string;
|
|
1962
2044
|
/** Current time in unix ms; defaults to `Date.now()`. */
|
|
@@ -2620,4 +2702,289 @@ interface CommonServiceOptions {
|
|
|
2620
2702
|
*/
|
|
2621
2703
|
declare function createCommonService(options?: CommonServiceOptions): ServiceHandler;
|
|
2622
2704
|
|
|
2623
|
-
|
|
2705
|
+
/** Hex Nostr public key. */
|
|
2706
|
+
type DmHexPubkey = string;
|
|
2707
|
+
/** Unix timestamp in seconds. */
|
|
2708
|
+
type DmTimestamp = number;
|
|
2709
|
+
/** Current runtime direct-message availability. */
|
|
2710
|
+
interface DmStatus {
|
|
2711
|
+
available: boolean;
|
|
2712
|
+
ownerPubkey?: DmHexPubkey;
|
|
2713
|
+
implementations: string[];
|
|
2714
|
+
capabilities: string[];
|
|
2715
|
+
}
|
|
2716
|
+
/** Query parameters for normalized DM conversation summaries. */
|
|
2717
|
+
interface DmConversationQuery {
|
|
2718
|
+
cursor?: string;
|
|
2719
|
+
limit?: number;
|
|
2720
|
+
}
|
|
2721
|
+
/** Public peer metadata safe for napplet display. */
|
|
2722
|
+
interface DmPeer {
|
|
2723
|
+
pubkey: DmHexPubkey;
|
|
2724
|
+
label?: string;
|
|
2725
|
+
avatar?: string;
|
|
2726
|
+
}
|
|
2727
|
+
/** A normalized direct or group conversation summary. */
|
|
2728
|
+
interface DmConversation {
|
|
2729
|
+
id: string;
|
|
2730
|
+
kind: 'direct' | 'group';
|
|
2731
|
+
participants: DmPeer[];
|
|
2732
|
+
subject?: string;
|
|
2733
|
+
unread: number;
|
|
2734
|
+
updatedAt?: DmTimestamp;
|
|
2735
|
+
}
|
|
2736
|
+
/** Page of normalized conversation summaries. */
|
|
2737
|
+
interface DmConversationPage {
|
|
2738
|
+
conversations: DmConversation[];
|
|
2739
|
+
cursor?: string;
|
|
2740
|
+
}
|
|
2741
|
+
/** Query parameters for message history within one conversation. */
|
|
2742
|
+
interface DmMessageQuery {
|
|
2743
|
+
conversationId: string;
|
|
2744
|
+
cursor?: string;
|
|
2745
|
+
limit?: number;
|
|
2746
|
+
}
|
|
2747
|
+
/** Runtime-normalized delivery state for a DM message. */
|
|
2748
|
+
type DmMessageStatus = 'sent' | 'delivered' | 'received' | 'failed';
|
|
2749
|
+
/** Normalized cleartext message visible to the napplet by runtime policy. */
|
|
2750
|
+
interface DmMessage {
|
|
2751
|
+
id: string;
|
|
2752
|
+
conversationId: string;
|
|
2753
|
+
senderPubkey: DmHexPubkey;
|
|
2754
|
+
createdAt: DmTimestamp;
|
|
2755
|
+
content: string;
|
|
2756
|
+
status: DmMessageStatus;
|
|
2757
|
+
}
|
|
2758
|
+
/** Page of normalized messages for one conversation. */
|
|
2759
|
+
interface DmMessagePage {
|
|
2760
|
+
messages: DmMessage[];
|
|
2761
|
+
cursor?: string;
|
|
2762
|
+
}
|
|
2763
|
+
/** Request to send a direct message. */
|
|
2764
|
+
interface DmSendRequest {
|
|
2765
|
+
conversationId?: string;
|
|
2766
|
+
recipients: DmHexPubkey[];
|
|
2767
|
+
content: string;
|
|
2768
|
+
clientMessageId?: string;
|
|
2769
|
+
}
|
|
2770
|
+
/** Result of a runtime-mediated send. */
|
|
2771
|
+
interface DmSendResult {
|
|
2772
|
+
ok: boolean;
|
|
2773
|
+
message: DmMessage;
|
|
2774
|
+
}
|
|
2775
|
+
/** Request to start live DM delivery. */
|
|
2776
|
+
interface DmSubscribeRequest {
|
|
2777
|
+
conversationId?: string;
|
|
2778
|
+
}
|
|
2779
|
+
/** Runtime-assigned live subscription identity. */
|
|
2780
|
+
interface DmSubscription {
|
|
2781
|
+
subscriptionId: string;
|
|
2782
|
+
}
|
|
2783
|
+
/** Generic boolean acknowledgement used by `dm.unsubscribe`. */
|
|
2784
|
+
interface DmOk {
|
|
2785
|
+
ok: boolean;
|
|
2786
|
+
}
|
|
2787
|
+
/** Relay pool contract for DM adapters. */
|
|
2788
|
+
interface DmRelayPool {
|
|
2789
|
+
subscribe(filters: NostrFilter[], callback: (item: NostrEvent | 'EOSE') => void, relayUrls?: string[]): {
|
|
2790
|
+
unsubscribe(): void;
|
|
2791
|
+
};
|
|
2792
|
+
publish(event: NostrEvent): void | Promise<void>;
|
|
2793
|
+
selectRelayTier(filters: NostrFilter[]): string[];
|
|
2794
|
+
isAvailable(): boolean;
|
|
2795
|
+
}
|
|
2796
|
+
/** DM adapter contract consumed by createDmService. */
|
|
2797
|
+
interface DmAdapter {
|
|
2798
|
+
status(): Promise<DmStatus> | DmStatus;
|
|
2799
|
+
conversations(query?: DmConversationQuery): Promise<DmConversationPage> | DmConversationPage;
|
|
2800
|
+
messages(query: DmMessageQuery): Promise<DmMessagePage> | DmMessagePage;
|
|
2801
|
+
send(request: DmSendRequest): Promise<DmSendResult>;
|
|
2802
|
+
subscribe(request: DmSubscribeRequest, onMessage: (message: DmMessage) => void): Promise<DmSubscription> | DmSubscription;
|
|
2803
|
+
unsubscribe(subscriptionId: string): Promise<DmOk> | DmOk;
|
|
2804
|
+
close?(): void;
|
|
2805
|
+
}
|
|
2806
|
+
|
|
2807
|
+
/**
|
|
2808
|
+
* dm-service.ts -- NAP-DM reference service.
|
|
2809
|
+
*
|
|
2810
|
+
* Routes `dm.*` envelopes to an injected adapter. The service owns request
|
|
2811
|
+
* correlation, per-window live subscription fan-out, and lifecycle cleanup;
|
|
2812
|
+
* adapters own protocol-specific transport/encryption/storage behavior.
|
|
2813
|
+
*/
|
|
2814
|
+
|
|
2815
|
+
/** Options for {@link createDmService}. */
|
|
2816
|
+
interface DmServiceOptions {
|
|
2817
|
+
/** Adapter that implements one or more chat backends under NAP-DM. */
|
|
2818
|
+
adapter: DmAdapter;
|
|
2819
|
+
}
|
|
2820
|
+
/** Created DM service. */
|
|
2821
|
+
interface DmService extends ServiceHandler {
|
|
2822
|
+
/** Close adapter resources. Idempotent when adapter close is idempotent. */
|
|
2823
|
+
dispose(): void;
|
|
2824
|
+
}
|
|
2825
|
+
/**
|
|
2826
|
+
* Create a NAP-DM service handler.
|
|
2827
|
+
*
|
|
2828
|
+
* @param options - DM adapter to route requests through.
|
|
2829
|
+
* @returns Service handler for `runtime.registerService('dm', handler)`.
|
|
2830
|
+
*/
|
|
2831
|
+
declare function createDmService(options: DmServiceOptions): DmService;
|
|
2832
|
+
|
|
2833
|
+
/** In-memory normalized DM store. */
|
|
2834
|
+
declare class DmMemoryStore {
|
|
2835
|
+
private readonly messagesByConversation;
|
|
2836
|
+
private readonly participantsByConversation;
|
|
2837
|
+
conversationIdFor(participants: readonly DmHexPubkey[]): string;
|
|
2838
|
+
upsertMessage(message: DmMessage, participants: readonly DmHexPubkey[]): DmMessage;
|
|
2839
|
+
conversations(query?: DmConversationQuery): DmConversationPage;
|
|
2840
|
+
messages(query: DmMessageQuery): DmMessagePage;
|
|
2841
|
+
}
|
|
2842
|
+
|
|
2843
|
+
/**
|
|
2844
|
+
* dm-nip17-adapter.ts -- concrete NIP-17 adapter for NAP-DM.
|
|
2845
|
+
*
|
|
2846
|
+
* Uses nostr-tools NIP-17 gift wrapping and an injected relay pool. The owner
|
|
2847
|
+
* key is shell/runtime-owned; napplets only see normalized cleartext messages.
|
|
2848
|
+
*/
|
|
2849
|
+
|
|
2850
|
+
/** Options for {@link createNip17DmAdapter}. */
|
|
2851
|
+
interface Nip17DmAdapterOptions {
|
|
2852
|
+
/** Shell-owned secret key used for NIP-17 seal creation/unwrapping. */
|
|
2853
|
+
ownerSecretKey: Uint8Array;
|
|
2854
|
+
/** Relay pool used for publish/subscribe. */
|
|
2855
|
+
relayPool: DmRelayPool;
|
|
2856
|
+
/** Default relays for NIP-17 DM traffic. */
|
|
2857
|
+
relays?: string[];
|
|
2858
|
+
/** Optional normalized message store. Defaults to an in-memory store. */
|
|
2859
|
+
store?: DmMemoryStore;
|
|
2860
|
+
}
|
|
2861
|
+
/**
|
|
2862
|
+
* Create a concrete NIP-17 NAP-DM adapter.
|
|
2863
|
+
*
|
|
2864
|
+
* @param options - Owner key, relay pool, relay hints, optional store.
|
|
2865
|
+
* @returns DM adapter for {@link createDmService}.
|
|
2866
|
+
*/
|
|
2867
|
+
declare function createNip17DmAdapter(options: Nip17DmAdapterOptions): DmAdapter;
|
|
2868
|
+
|
|
2869
|
+
/**
|
|
2870
|
+
* dm-ndr-adapter.ts -- Nostr Double Ratchet adapter for NAP-DM.
|
|
2871
|
+
*
|
|
2872
|
+
* Kehto accepts a structural NDR runtime instead of depending directly on the
|
|
2873
|
+
* moving nostr-double-ratchet package API. Hosts can pass NdrRuntime instances.
|
|
2874
|
+
*/
|
|
2875
|
+
|
|
2876
|
+
/** Minimal event shape returned by NDR runtimes for sent or received messages. */
|
|
2877
|
+
interface NdrRumorLike {
|
|
2878
|
+
id: string;
|
|
2879
|
+
pubkey?: string;
|
|
2880
|
+
created_at?: number;
|
|
2881
|
+
content?: string;
|
|
2882
|
+
}
|
|
2883
|
+
/** Minimal structural subset of nostr-double-ratchet NdrRuntime. */
|
|
2884
|
+
interface NdrRuntimeLike {
|
|
2885
|
+
getState?(): {
|
|
2886
|
+
ownerPubkey?: string | null;
|
|
2887
|
+
currentDevicePubkey?: string | null;
|
|
2888
|
+
};
|
|
2889
|
+
initForOwner?(ownerPubkey: string): Promise<unknown>;
|
|
2890
|
+
setupUser?(pubkey: string, ownerPubkey?: string): Promise<void>;
|
|
2891
|
+
sendMessage(recipientPubkey: string, content: string, options?: unknown, ownerPubkey?: string): Promise<NdrRumorLike>;
|
|
2892
|
+
onSessionEvent(callback: (event: NdrRumorLike, from: string, meta?: unknown) => void): () => void;
|
|
2893
|
+
close?(): void;
|
|
2894
|
+
}
|
|
2895
|
+
interface NdrRelayTransport {
|
|
2896
|
+
nostrSubscribe(filter: NostrFilter, onEvent: (event: NostrEvent) => void): () => void;
|
|
2897
|
+
nostrFetch(filter: NostrFilter): Promise<NostrEvent[]>;
|
|
2898
|
+
nostrPublish(event: Partial<NostrEvent>, innerEventId?: string): Promise<NostrEvent>;
|
|
2899
|
+
}
|
|
2900
|
+
interface NdrRelayTransportOptions {
|
|
2901
|
+
relayPool: DmRelayPool;
|
|
2902
|
+
publishSecretKey?: Uint8Array;
|
|
2903
|
+
relays?: string[];
|
|
2904
|
+
fetchTimeoutMs?: number;
|
|
2905
|
+
}
|
|
2906
|
+
/** Options for {@link createNdrDmAdapter}. */
|
|
2907
|
+
interface NdrDmAdapterOptions {
|
|
2908
|
+
runtime: NdrRuntimeLike;
|
|
2909
|
+
ownerPubkey: string;
|
|
2910
|
+
store?: DmMemoryStore;
|
|
2911
|
+
available?: boolean;
|
|
2912
|
+
}
|
|
2913
|
+
/** Build the transport contract expected by nostr-double-ratchet over Kehto relay service hooks. */
|
|
2914
|
+
declare function createNdrRelayTransport(options: NdrRelayTransportOptions): NdrRelayTransport;
|
|
2915
|
+
/** Create an NDR-backed NAP-DM adapter. */
|
|
2916
|
+
declare function createNdrDmAdapter(options: NdrDmAdapterOptions): DmAdapter;
|
|
2917
|
+
|
|
2918
|
+
/** Cordn DM client contract. */
|
|
2919
|
+
interface CordnDmClient {
|
|
2920
|
+
status?(): Promise<Partial<DmStatus>> | Partial<DmStatus>;
|
|
2921
|
+
conversations(query?: DmConversationQuery): Promise<DmConversationPage> | DmConversationPage;
|
|
2922
|
+
messages(query: DmMessageQuery): Promise<DmMessagePage> | DmMessagePage;
|
|
2923
|
+
send(request: DmSendRequest): Promise<DmSendResult>;
|
|
2924
|
+
subscribe(request: DmSubscribeRequest, onMessage: (message: DmMessage) => void): Promise<DmSubscription> | DmSubscription;
|
|
2925
|
+
unsubscribe(subscriptionId: string): Promise<{
|
|
2926
|
+
ok: boolean;
|
|
2927
|
+
}> | {
|
|
2928
|
+
ok: boolean;
|
|
2929
|
+
};
|
|
2930
|
+
close?(): void;
|
|
2931
|
+
}
|
|
2932
|
+
interface CordnGroupMessage {
|
|
2933
|
+
cursor: number;
|
|
2934
|
+
gid: string;
|
|
2935
|
+
msg_64: string;
|
|
2936
|
+
at: number;
|
|
2937
|
+
}
|
|
2938
|
+
interface CordnCoordinatorSubscription {
|
|
2939
|
+
stream: AsyncIterable<CordnGroupMessage>;
|
|
2940
|
+
result: Promise<{
|
|
2941
|
+
subscribed: true;
|
|
2942
|
+
}>;
|
|
2943
|
+
abort(reason?: string): Promise<void>;
|
|
2944
|
+
}
|
|
2945
|
+
interface CordnCoordinatorClient {
|
|
2946
|
+
PostGroupMessage(input: {
|
|
2947
|
+
msg_64: string;
|
|
2948
|
+
}): Promise<{
|
|
2949
|
+
cursor: number;
|
|
2950
|
+
gid: string;
|
|
2951
|
+
at: number;
|
|
2952
|
+
}>;
|
|
2953
|
+
FetchGroupMessages(input: {
|
|
2954
|
+
gid: string;
|
|
2955
|
+
after?: number;
|
|
2956
|
+
}): Promise<{
|
|
2957
|
+
messages: CordnGroupMessage[];
|
|
2958
|
+
}>;
|
|
2959
|
+
SubscribeGroupMessages(input: {
|
|
2960
|
+
gid: string;
|
|
2961
|
+
after?: number;
|
|
2962
|
+
}): Promise<CordnCoordinatorSubscription>;
|
|
2963
|
+
close?(): void;
|
|
2964
|
+
}
|
|
2965
|
+
interface CordnCodecResult {
|
|
2966
|
+
msg_64: string;
|
|
2967
|
+
gid: string;
|
|
2968
|
+
}
|
|
2969
|
+
interface CordnRelayCoordinatorOptions {
|
|
2970
|
+
relayPool: DmRelayPool;
|
|
2971
|
+
ownerSecretKey: Uint8Array;
|
|
2972
|
+
relays?: string[];
|
|
2973
|
+
kind?: number;
|
|
2974
|
+
fetchTimeoutMs?: number;
|
|
2975
|
+
}
|
|
2976
|
+
/** Options for {@link createCordnDmAdapter}. */
|
|
2977
|
+
interface CordnDmAdapterOptions {
|
|
2978
|
+
client?: CordnDmClient;
|
|
2979
|
+
coordinator?: CordnCoordinatorClient;
|
|
2980
|
+
ownerPubkey?: string;
|
|
2981
|
+
defaultGroupId?: string;
|
|
2982
|
+
store?: DmMemoryStore;
|
|
2983
|
+
encodeMessage?(request: DmSendRequest, ownerPubkey?: string): CordnCodecResult;
|
|
2984
|
+
decodeMessage?(message: CordnGroupMessage, ownerPubkey?: string): DmMessage;
|
|
2985
|
+
}
|
|
2986
|
+
declare function createCordnRelayCoordinatorClient(options: CordnRelayCoordinatorOptions): CordnCoordinatorClient;
|
|
2987
|
+
/** Create a Cordn/ContextVM-backed NAP-DM adapter. */
|
|
2988
|
+
declare function createCordnDmAdapter(options: CordnDmAdapterOptions): DmAdapter;
|
|
2989
|
+
|
|
2990
|
+
export { type AudioServiceOptions, type AudioSource, type BleServiceContext, type BleServiceOptions, type CacheServiceOptions, type CatalogIntentResolver, type CatalogIntentResolverOptions, type CommonServiceContext, type CommonServiceOptions, type ConfigSchemaValidation, type ConfigService, type ConfigServiceOptions, type CoordinatedRelayOptions, type CordnCodecResult, type CordnCoordinatorClient, type CordnCoordinatorSubscription, type CordnDmAdapterOptions, type CordnDmClient, type CordnGroupMessage, type CordnRelayCoordinatorOptions, type DmAdapter, type DmConversation, type DmConversationPage, type DmConversationQuery, type DmHexPubkey, DmMemoryStore, type DmMessage, type DmMessagePage, type DmMessageQuery, type DmMessageStatus, type DmOk, type DmPeer, type DmRelayPool, type DmSendRequest, type DmSendResult, type DmService, type DmServiceOptions, type DmStatus, type DmSubscribeRequest, type DmSubscription, type DmTimestamp, type HostCacheBridge, type HostKeyEvent, type HostKeysBridge, type HostMediaBridge, type HttpUploaderOptions, type HttpUploaderRails, type IdentityServiceOptions, type IntentArchetypeSupport, type IntentAvailability, type IntentBehavior, type IntentCandidate, type IntentCatalogEntry, type IntentHandlerPreference, type IntentOpenParams, type IntentRequest, type IntentResolver, type IntentResolverContext, type IntentResult, type IntentServiceOptions, type IntentWindowController, type KeysServiceOptions, type LinkOpenContext, type LinkServiceOptions, type ListsServiceContext, type ListsServiceOptions, type ManifestArchetypeInput, type MaybePromise, type MediaMetadataLike, type MediaPlaybackOwner, type MediaServiceOptions, type MediaSessionCreateOptions, type MediaSessionTarget, type MediaSourceRef, type NdrDmAdapterOptions, type NdrRelayTransport, type NdrRelayTransportOptions, type NdrRumorLike, type NdrRuntimeLike, type Nip17DmAdapterOptions, type NostrTag, type Notification, type NotificationServiceOptions, type NotifyServiceOptions, type OutboxEventOptions, type OutboxEventResult, type OutboxPublishOptions, type OutboxPublishResult, type OutboxQueryOptions, type OutboxRelayPlan, type OutboxRelayPool, type OutboxResult, type OutboxRouter, type OutboxRouterSubscription, type OutboxServiceOptions, type OutboxStrategy, type OutboxSubscribeOptions, type OutboxSubscriptionSink, type OutboxTarget, type RailServerConfig, type RelayListEntry, type RelayPoolOutboxRouterOptions, type RelayPoolServiceOptions, type ResourceInfo, type ResourceInfoContext, type ResourceInfoProvider, type ResourceSchemeInfo, type ResourceService, type ResourceServiceOptions, type SerialServiceContext, type SerialServiceOptions, type SignEvent, type ThemeService, type ThemeServiceOptions, type UploadDimensions, type UploadInfo, type UploadInfoContext, type UploadInfoProvider, type UploadRail, type UploadRailInfo, type UploadRequest, type UploadResult, type UploadServiceOptions, type UploadState, type UploadStatus, type Uploader, type UploaderContext, type WebrtcServiceContext, type WebrtcServiceOptions, createAudioService, createBleService, createBrowserMediaBridge, createCacheService, createCatalogIntentResolver, createCommonService, createConfigService, createCoordinatedRelay, createCordnDmAdapter, createCordnRelayCoordinatorClient, createDmService, createHttpUploader, createIdentityService, createIntentService, createKeysService, createLinkService, createListsService, createMediaService, createNdrDmAdapter, createNdrRelayTransport, createNip17DmAdapter, createNotificationService, createNotifyService, createOutboxService, createRelayPoolOutboxRouter, createRelayPoolService, createResourceService, createSerialService, createThemeService, createUploadService, createWebrtcService, manifestToIntentCatalogEntry };
|