@recursiv/sdk 0.7.58 → 0.7.62

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
@@ -75,7 +75,7 @@ for await (const chunk of r.agents.chatStream(agent.id, { message: 'Hello!' }))
75
75
  | Resource | Key methods |
76
76
  |----------|------------|
77
77
  | `r.agents` | `create`, `update`, `chat`, `chatStream`, `retryChatStream`, `grantProjectAccess`, `conversations` |
78
- | `r.e2ee` | `status`, `registerDevice`, `devices`, `revokeDevice` (`{ cascade }` to also revoke devices approved through it; 409 `has_dependents` otherwise), `publishKeyPackages`, `keyPackageStatus`, `claimKeyPackage`, `appendEvent`, `events`, `acknowledge`, `conversations`; device linking by scan: `createLink`, `link`, `scannedLink`, `approveLink`, `completeLink`, `linkProgress`, `cancelLink` (flag-gated E2EE v2 transport; its doorbell is `r.realtime.onE2eeEvent`, which carries a small message's stored ciphertext to the owner's own sockets; link and device changes arrive on `r.realtime.onE2eeLink` and `onE2eeDevices`) |
78
+ | `r.e2ee` | `status`, `registerDevice`, `devices`, `revokeDevice` (`{ cascade }` to also revoke devices approved through it; 409 `has_dependents` otherwise), `requestResetCode` and `resetAccount` (reset encrypted chat with an emailed code where `status().accountReset`), `publishKeyPackages`, `keyPackageStatus`, `claimKeyPackage`, `appendEvent`, `events`, `acknowledge`, `conversations`; device linking by scan: `createLink`, `link`, `scannedLink`, `approveLink`, `completeLink`, `linkProgress`, `cancelLink` (flag-gated E2EE v2 transport; its doorbell is `r.realtime.onE2eeEvent`, which carries a small message's stored ciphertext to the owner's own sockets; link and device changes arrive on `r.realtime.onE2eeLink` and `onE2eeDevices`) |
79
79
  | `r.brain` | `sendMessage` |
80
80
  | `r.commands` | `execute`, `gatePrompt` |
81
81
  | `r.projectBrain` | `tasks`, `decisions`, `milestones`, `completeTask`, `usage` |
@@ -96,7 +96,7 @@ for await (const chunk of r.agents.chatStream(agent.id, { message: 'Hello!' }))
96
96
  | `r.posts` | `create`, `update`, `list`, `liked`, `bookmarked`, `bookmark`, `unbookmark`, `search`, `replies`, `react` |
97
97
  | `r.bookmarks` | `save`, `unsave`, `posts`, `list`, `keys`, `merge` — the member's saved posts, open-network posts and articles, synced across devices |
98
98
  | `r.communities` | `create`, `join`, `search`, `members` |
99
- | `r.chat` | `send`, `dm`, `createGroup`, `messages` (cursor paging), `acceptRequest`, `declineRequest`, `leave`, `deleteConversation` |
99
+ | `r.chat` | `send`, `dm`, `createGroup` (`encrypted: true` for an end-to-end encrypted group, 0.7.59), `messages` (cursor paging), `acceptRequest`, `declineRequest`, `leave`, `deleteConversation`; a private group's admin: `addMembers`, `removeMember`, `updateGroup` (0.7.59) |
100
100
  | `r.tags` | `create`, `list` |
101
101
  | `r.uploads` | `uploadMedia` — upload post/chat bytes end to end |
102
102
  | `r.video` | `entitlement` (may the caller publish video, and how much is left), `createUpload`, `getStatus`, `getPlaybackToken` |
@@ -115,7 +115,7 @@ for await (const chunk of r.agents.chatStream(agent.id, { message: 'Hello!' }))
115
115
  | `r.admin` | User management, stats, content reports (`listReports`, `resolveReport`, `dismissReport`) |
116
116
  | `r.dispatcher` | Task queue, claims, signals, outcomes, webhooks |
117
117
  | `r.goals` | Org goals with task rollups (group dispatcher tasks) |
118
- | `r.protocols` | Private Minds safety: `sourceControls` (current enablement and saved choices; filter with `control`, each item may carry a `display` label), `setSourceControl`, `onSourceControlChange`, `reportSource`. Delegated accounts: `nativeSocialAccounts`, `startNativeSocialConnection`, `finishNativeSocialConnection`, `disconnectNativeSocialAccount`. Native follows: `nativeFollowStates` (every connected account's state for one source, one read), `nativeFollowState`, `prepareNativeFollow`, `submitNativeFollow`, `nativeFollowStatus` (native following or pending approval, distinct from a Minds feed subscription; preserve the complete signed Nostr list). Native reposts and undo: `nativeRepostState`, `prepareNativeRepost`, `submitNativeRepost`, `nativeRepostStatus` (public posts, explicit approval, connected account, no uncertain retries). Native likes and unlikes: `nativeLikeState`, `prepareNativeLike`, `submitNativeLike`, `nativeLikeStatus` (connected authority, app enablement and explicit approval; resume pending actions instead of duplicating them). Reviewed replies and optional linked posts: `prepareNativeReply`, `submitNativeReply`, `nativeReplyStatus`, `nativeReplyHistory`, `prepareNativeReplyRemoval`, `removeNativeReply` (require deployed API support and app enablement). Keyless shared post links: `sharedNetworks(projectId)`, `getSharedConversation(projectId, { protocol, post, readRef? })`. Member public reading: `searchPublicPosts` (selected account required for Bluesky/ActivityPub; public Nostr search), `getConnectedSocialConversation` (preserve result readerAccountId/readRef), `publicNetworks`, `searchPublicProfiles`, `getPublicProfile`, `getPublicAuthorFeed`, `getFollowingFeed`, `getPublicConversation`, `getPublicTrends`, `getPublicTrendFeed`; radar stories: `getPublicRadarStory` (one story by id with its posts; one that left the radar within its minimum lifetime, or within the last half hour, still answers live with `liveUntil` and the story that continues it; one that has left for longer comes with its archived copy and the live story it continues as; the id may be a World Today edition story's, and the answer then names it in `editionStory` under the story's radar id), keyless `getSharedRadarStory(projectId, { cluster })` and `getSharedRadarPosts(projectId, { cluster })` (keyless reads carry images and videos only from outlets and members marked `visitorMedia`; signed-in reads keep all media, so a share card uses only those); private app subscriptions: `listSubscriptions`, `subscribeToProfile`, `unsubscribeFromProfile`, `onSubscriptionChange`. `list` returns bounded adapter `maturity`, `limitations`, and exhaustive `supported`/`planned`/`unsupported` implementation capabilities (not provider health or enablement); settings, candidate refresh/status, search, and read-only quarantined candidate review via `listCandidates` / `getCandidate` |
118
+ | `r.protocols` | Private Minds safety: `sourceControls` (current enablement and saved choices; filter with `control`, each item may carry a `display` label), `setSourceControl`, `onSourceControlChange`, `reportSource`. Delegated accounts: `nativeSocialAccounts`, `startNativeSocialConnection`, `finishNativeSocialConnection`, `disconnectNativeSocialAccount`. Native follows: `nativeFollowStates` (every connected account's state for one source, one read), `nativeFollowState`, `prepareNativeFollow`, `submitNativeFollow`, `nativeFollowStatus` (native following or pending approval, distinct from a Minds feed subscription; preserve the complete signed Nostr list). Native reposts and undo: `nativeRepostState`, `prepareNativeRepost`, `submitNativeRepost`, `nativeRepostStatus` (public posts, explicit approval, connected account, no uncertain retries). Native likes and unlikes: `nativeLikeState`, `prepareNativeLike`, `submitNativeLike`, `nativeLikeStatus` (connected authority, app enablement and explicit approval; resume pending actions instead of duplicating them). Reviewed replies and optional linked posts: `prepareNativeReply`, `submitNativeReply`, `nativeReplyStatus`, `nativeReplyHistory`, `prepareNativeReplyRemoval`, `removeNativeReply` (require deployed API support and app enablement). Keyless shared post links: `sharedNetworks(projectId)`, `getSharedConversation(projectId, { protocol, post, readRef? })`. Member public reading: `searchPublicPosts` (selected account required for Bluesky/ActivityPub; public Nostr search), `getConnectedSocialConversation` (preserve result readerAccountId/readRef), `publicNetworks`, `searchPublicProfiles`, `getPublicProfile`, `getPublicAuthorFeed`, `getFollowingFeed`, `getPublicConversation`, `getPublicTrends`, `getPublicTrendFeed`; radar stories: `getPublicRadarStory` (one story by id with its posts; one that left the radar within its minimum lifetime, or within the last half hour, still answers live with `liveUntil` and the story that continues it; one that has left for longer comes with its archived copy and the live story it continues as; the id may be a World Today edition story's, and the answer then names it in `editionStory` under the story's radar id), keyless `getSharedRadarStory(projectId, { cluster })` and `getSharedRadarPosts(projectId, { cluster })` (keyless reads carry images and videos only from outlets and members marked `visitorMedia`; signed-in reads keep all media, so a share card uses only those); the Viral read (fastest-moving posts across Bluesky, the Fediverse, Nostr and Minds, each against its own network's pace; 0.7.59): `getPublicViral({ network?, category?, media?: 'video', limit?: 5 | 10 | 20 | 40, cursor?, compass? })` under the member's key and keyless `getSharedViral(projectId, params)` (visitors: `compass` `all` or `hide` only; a visitor's `media: 'video'` read can carry items whose video the server withheld, so filter with the exported `viralItemHasVideo` before a video player; `item.post` narrows on `item.protocol`). `status: 'off'` resolves with no items until the app enables the read, and `getSharedViral` also resolves an older API's 401 `missing_api_key` as off; `getPublicViral` throws every 401 and 403, so a session failure is never read as off; private app subscriptions: `listSubscriptions`, `subscribeToProfile`, `unsubscribeFromProfile`, `onSubscriptionChange`. `list` returns bounded adapter `maturity`, `limitations`, and exhaustive `supported`/`planned`/`unsupported` implementation capabilities (not provider health or enablement); settings, candidate refresh/status, search, and read-only quarantined candidate review via `listCandidates` / `getCandidate` |
119
119
 
120
120
  Full reference: see [llm.md](./llm.md) (ships with this package) or the type definitions in `dist/`.
121
121
 
@@ -364,7 +364,7 @@ try {
364
364
  }
365
365
  ```
366
366
 
367
- Auto-retry is built in. 429 and 5xx responses retry with exponential backoff (configurable via `maxRetries`, default 2). A 429 with `X-RateLimit-Scope: action` refuses one member action past its budget and is never retried: its `RateLimitError` has `scope: 'action'` and `resetAt` (a `Date`, when that action's budget reopens).
367
+ Auto-retry is built in. 429 and 5xx responses retry with exponential backoff (configurable via `maxRetries`, default 2). A 429 with `X-RateLimit-Scope: action` refuses one member action past its budget and is never retried: its `RateLimitError` has `scope: 'action'` and `resetAt` (a `Date`, when that action's budget reopens). A read that holds its own deadline can ask once with `retry: false` in its params: `r.posts.list({ ...params, retry: false })` and `r.curator.forYou({ ...params, retry: false })` throw the first 5xx or 429 with no retry and no `Retry-After` sleep, and never send `retry` to the server.
368
368
 
369
369
  ## Pagination
370
370
 
@@ -653,8 +653,13 @@ sources; create a new session to refresh exhausted source windows. A topics netw
653
653
  (Bluesky) is read one topic page at a time; in a category the catalog's previews are not
654
654
  judged to be in it, so a read walks into the topics at once, and walks past a topic the
655
655
  provider no longer lists (`trend_unavailable`) or one with nothing in the category, up
656
- to five topic pages a read, so a page reaches a topic that carries posts. Any other
657
- failure marks the source failed until `retryFailed()`.
656
+ to five topic pages a read, so a page reaches a topic that carries posts. A network read
657
+ that fails for a passing reason (past the 15 s page deadline, a dropped connection, a 429
658
+ or a 5xx) leaves the network out of that page and the next, named in `retryingSources`
659
+ until a later page asks it again (from the page after, when its turn comes), up to two
660
+ times in a row. Any other failure, or one past that, marks the source failed
661
+ (`failedSources`) until `retryFailed()`. The Minds read is asked once and is never
662
+ retried this way: any failure of it is in `failedSources` on that page.
658
663
 
659
664
  `sdk.discovery.createPersonalFeed({ networks, category?, learning?, recommend? })`
660
665
  builds the same kind of session for a member's For you tab: its Minds slot reads
@@ -664,6 +669,18 @@ and says whether the member is personalized yet (`meta.personalized`). With a
664
669
  `category` (the member's first), the session also reads open-network posts from it;
665
670
  without, it is Minds only. It never carries the radar.
666
671
 
672
+ Both take a Politics choice, `compass` (`all`, `mix`, `hide`, or cells in the order
673
+ `lo,co,ro,lm,cm,rm,ll,cl,rl`, optionally `np`), and send it with every Minds read
674
+ (`posts.list` and `curator.forYou` take it too). Each such page says what it did in
675
+ `meta.compass_filter` (`status` `applied` or `unavailable`, and counts only), and each session
676
+ page carries its Minds read's answer as `page.compass` (`unavailable`: the page is unfiltered). Only Minds
677
+ posts are filtered, so a view that leaves posts out reads best with `source: 'minds'`.
678
+ The catalog lists `compass_filter` on every network when the filter is served to the viewer.
679
+ Hide politics (`compass: 'hide'`) also applies on its own, with or without compass judgments on the server, to
680
+ `sdk.discovery.videos`, `protocols.getPublicTrends` and the radar (`getPublicRadar`, keyless `getSharedRadar`; 0.7.62):
681
+ it leaves out what is categorised politics (a story not themed yet, or `mixed`, too) and says what it did in
682
+ `meta.compass_filter`. These reads answer a side or Mix unfiltered, marked `unavailable`.
683
+
667
684
  `sdk.discovery.recommendations({ kind, category?, limit?, session?, exclude? })` is
668
685
  the app's one recommender for suggestion rails: `kind` is `member`, `group`, `tag`,
669
686
  `network_account` or `story`, and `category` is `all` or a browse category id. It
@@ -682,14 +699,20 @@ history: every page's `meta.next` is `{ offset }`, `{ cursor }` or `null`, and w
682
699
  stage ends `meta.fallover` lists where to go, in order: `category_older` (the keyset
683
700
  cursor `next` also carries), `category_network` (the same category on the open
684
701
  networks), the member's next categories (`via` names the order they came from), `for_you`
685
- and `all`. A `DiscoveryFeedSession` follows the cursor itself and reports the Minds
686
- feed's `fallover` on its pages. `sdk.discovery.category({ category, session? })` answers a
702
+ and `all`. A `feed` step (`ref`, the next feed's ref; 0.7.60) is declared but not sent yet:
703
+ skip a kind your app cannot open. A `DiscoveryFeedSession` follows the cursor itself and
704
+ reports the Minds feed's `fallover` on its pages, leaving out any step this SDK does not
705
+ know or a malformed one. `sdk.discovery.category({ category, session? })` answers a
687
706
  category's surface in one call: `stories`, `network` and `clips` (each shared per app and
688
707
  category, refreshed after 30 s, kept up to 300 s and warmed as the warmer reaches the category, then filtered for the viewer on every call: the cached safety verdicts of story members, network posts and clips again, the term list, the viewer's blocks and mutes over clips, and the member's own hidden sources over network posts and story members) and the
689
708
  viewer's `people` and `groups`; a section that timed out, failed or is off is empty with a
690
709
  `reason` for that request only (a failure is never cached, so asking again retries it), and one this
691
710
  key may not read is empty with `refused` (`stories` and `network` need the member's own app
692
- key with `users:read`; `people` and `groups` need `users:read`). A plain category page
711
+ key with `users:read`; `people` and `groups` need `users:read`). `sdk.discovery.videos({ category?, limit?, cursor?, offset?, compass? })`
712
+ is Watch's Minds read: the app's public video posts in hot order, from one list the server shares among every viewer of
713
+ the app and rebuilds about once a minute, each post checked again on every call under the public floors and the viewer's
714
+ blocks and mutes, in the `Post` shape with the viewer's own `user_reaction` and `reposted_by_viewer_id` (page on
715
+ `meta.next_cursor`; a feed session's Minds slot can read it as its `list`). A plain category page
693
716
  (`posts.list({ category })` with no other filter) reads on past a slice the safety floors
694
717
  thinned, up to six reads, until it holds `limit` posts or its candidates end: `meta.scanned`
695
718
  is how many it examined (the next offset is `offset + scanned`), and the stage ends on the
package/dist/errors.d.ts CHANGED
@@ -84,3 +84,16 @@ export declare class RateLimitError extends RecursivError {
84
84
  export declare class ConflictError extends RecursivError {
85
85
  constructor(body: ApiErrorBody['error']);
86
86
  }
87
+ /**
88
+ * `email.send` answered 200 but sent to nobody: every recipient was held
89
+ * (no marketing consent, suppressed, preference off). Thrown so a caller that
90
+ * only checks for success cannot report mail as sent. `details` carries the
91
+ * per-recipient `messages` with each `reason`.
92
+ */
93
+ export declare class EmailNotSentError extends RecursivError {
94
+ constructor(body: {
95
+ message: string;
96
+ hint?: string;
97
+ details?: unknown;
98
+ });
99
+ }
package/dist/errors.js CHANGED
@@ -189,3 +189,15 @@ export class ConflictError extends RecursivError {
189
189
  this.name = 'ConflictError';
190
190
  }
191
191
  }
192
+ /**
193
+ * `email.send` answered 200 but sent to nobody: every recipient was held
194
+ * (no marketing consent, suppressed, preference off). Thrown so a caller that
195
+ * only checks for success cannot report mail as sent. `details` carries the
196
+ * per-recipient `messages` with each `reason`.
197
+ */
198
+ export class EmailNotSentError extends RecursivError {
199
+ constructor(body) {
200
+ super(200, { type: 'email_not_sent', code: 'email_held', message: body.message, hint: body.hint, details: body.details });
201
+ this.name = 'EmailNotSentError';
202
+ }
203
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * FeedDefinition v1, as apps read and write it: the one recipe behind every feed (a list of sources read as one union,
3
+ * a ranking mode, optional filters and exclusions). Types and constants only; the server
4
+ * (packages/server/src/features/feeds/FeedDefinition.ts) validates, canonicalises and digests a definition, and its
5
+ * FeedDefinitionSdkContract test holds these constants equal to its own.
6
+ *
7
+ * Nothing serves a definition yet: no route reads one before the cutover. Discover's built-in categories, All and
8
+ * For you are definitions held in code on the server (refs `builtin:category:<id>`, `builtin:all`, `builtin:for_you`).
9
+ *
10
+ * A definition never holds the viewer's safe/open setting, blocks or mutes, or a compass Mix or Choose-sides choice:
11
+ * `filters.politics: 'hide'` is the only Politics value a feed stores.
12
+ */
13
+ export declare const FEED_DEFINITION_VERSION: 1;
14
+ /** Sources a definition may name, read as one union. Only `builtin:all` and `builtin:for_you` have none. */
15
+ export declare const FEED_SOURCES_MAX = 50;
16
+ /** The largest canonical definition the server keeps, in bytes. */
17
+ export declare const FEED_DEFINITION_MAX_BYTES: number;
18
+ export declare const FEED_SOURCE_KINDS: readonly ["category", "tag", "account", "community", "collection", "list", "story", "bsky_feed", "bsky_list", "bsky_starterpack", "nostr_set"];
19
+ export type FeedSourceKind = typeof FEED_SOURCE_KINDS[number];
20
+ export declare const FEED_RANKING_MODES: readonly ["hot", "new", "top", "for_you", "viral"];
21
+ export type FeedRankingMode = typeof FEED_RANKING_MODES[number];
22
+ export declare const FEED_RANKING_RANGES: readonly ["24h", "7d", "30d", "1y"];
23
+ export type FeedRankingRange = typeof FEED_RANKING_RANGES[number];
24
+ export declare const FEED_MEDIA: readonly ["any", "images", "video", "longread"];
25
+ export type FeedMedia = typeof FEED_MEDIA[number];
26
+ export declare const FEED_NETWORKS: readonly ["minds", "bluesky", "activitypub", "nostr"];
27
+ export type FeedNetwork = typeof FEED_NETWORKS[number];
28
+ /** Source kinds a topical feed may hold (with a hot, new or top ranking); any other feed is 'wide'. */
29
+ export declare const FEED_TOPICAL_SOURCE_KINDS: readonly ["category", "tag", "account", "community", "list", "collection", "story"];
30
+ export declare const FEED_TOPICAL_MODES: readonly ["hot", "new", "top"];
31
+ /** The one field that names what each source kind reads. */
32
+ export declare const FEED_SOURCE_KEY: {
33
+ readonly category: "id";
34
+ readonly tag: "slug";
35
+ readonly account: "ref";
36
+ readonly community: "id";
37
+ readonly collection: "id";
38
+ readonly list: "id";
39
+ readonly story: "clusterId";
40
+ readonly bsky_feed: "uri";
41
+ readonly bsky_list: "uri";
42
+ readonly bsky_starterpack: "uri";
43
+ readonly nostr_set: "naddr";
44
+ };
45
+ /** An account by its native id: a Minds user, an atproto DID, a Nostr hex pubkey or a WebFinger account. */
46
+ export type FeedAccountRef = `user:${string}` | `did:${string}` | `nostr:${string}` | `acct:${string}`;
47
+ export type FeedSource =
48
+ /** A Discover category id, as `posts.categories()` lists them. */
49
+ {
50
+ kind: 'category';
51
+ id: string;
52
+ }
53
+ /** A hashtag, without the `#`. */
54
+ | {
55
+ kind: 'tag';
56
+ slug: string;
57
+ } | {
58
+ kind: 'account';
59
+ ref: FeedAccountRef;
60
+ } | {
61
+ kind: 'community';
62
+ id: string;
63
+ }
64
+ /** A member's collection of saved posts, or a list (after the cutover). */
65
+ | {
66
+ kind: 'collection';
67
+ id: string;
68
+ } | {
69
+ kind: 'list';
70
+ id: string;
71
+ }
72
+ /** A World Today story, by its radar cluster id. */
73
+ | {
74
+ kind: 'story';
75
+ clusterId: string;
76
+ }
77
+ /** Bluesky feeds, lists and starter packs by their at:// record URI (after the cutover). */
78
+ | {
79
+ kind: 'bsky_feed';
80
+ uri: string;
81
+ } | {
82
+ kind: 'bsky_list';
83
+ uri: string;
84
+ } | {
85
+ kind: 'bsky_starterpack';
86
+ uri: string;
87
+ }
88
+ /** A Nostr people, interest, bookmark or curation set by its NIP-19 naddr (after the cutover). */
89
+ | {
90
+ kind: 'nostr_set';
91
+ naddr: string;
92
+ };
93
+ export interface FeedRanking {
94
+ mode: FeedRankingMode;
95
+ range?: FeedRankingRange;
96
+ }
97
+ export interface FeedFilters {
98
+ /** Absent means any media. */
99
+ media?: FeedMedia;
100
+ /** Absent means every network. */
101
+ networks?: FeedNetwork[];
102
+ /** The only Politics value a feed stores. Mix and Choose sides stay the viewer's own. */
103
+ politics?: 'hide';
104
+ /** BCP 47 language tags such as `en` or `pt-br`; at most 10. */
105
+ languages?: string[];
106
+ }
107
+ export interface FeedExclude {
108
+ /** At most 50 tags. */
109
+ tags?: string[];
110
+ /** At most 50 accounts. */
111
+ accounts?: FeedAccountRef[];
112
+ }
113
+ export interface FeedDefinition {
114
+ v: typeof FEED_DEFINITION_VERSION;
115
+ /** 1 to 50, read as one union; empty only for `builtin:all` and `builtin:for_you`. */
116
+ sources: FeedSource[];
117
+ ranking: FeedRanking;
118
+ filters?: FeedFilters;
119
+ exclude?: FeedExclude;
120
+ }
121
+ export type BuiltinFeedRef = `builtin:category:${string}` | 'builtin:all' | 'builtin:for_you';
122
+ /** A feed's address: a built-in, a member feed's current version (`feed:<uuid>`), or one version of it. */
123
+ export type FeedRef = BuiltinFeedRef | `feed:${string}` | `feed:${string}@${number}`;
124
+ /** Computed by the server, never stored: 'anon' feeds are ranked once and may be shared; 'viewer' feeds are ranked per viewer. */
125
+ export type FeedAudience = 'anon' | 'viewer';
126
+ /** Computed by the server: 'wide' feeds leave out Bluesky authors who asked not to be recommended. */
127
+ export type FeedConsentClass = 'topical' | 'wide';
128
+ /** The built-in feed for a Discover category. */
129
+ export declare function builtinCategoryFeedRef(category: string): BuiltinFeedRef;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * FeedDefinition v1, as apps read and write it: the one recipe behind every feed (a list of sources read as one union,
3
+ * a ranking mode, optional filters and exclusions). Types and constants only; the server
4
+ * (packages/server/src/features/feeds/FeedDefinition.ts) validates, canonicalises and digests a definition, and its
5
+ * FeedDefinitionSdkContract test holds these constants equal to its own.
6
+ *
7
+ * Nothing serves a definition yet: no route reads one before the cutover. Discover's built-in categories, All and
8
+ * For you are definitions held in code on the server (refs `builtin:category:<id>`, `builtin:all`, `builtin:for_you`).
9
+ *
10
+ * A definition never holds the viewer's safe/open setting, blocks or mutes, or a compass Mix or Choose-sides choice:
11
+ * `filters.politics: 'hide'` is the only Politics value a feed stores.
12
+ */
13
+ export const FEED_DEFINITION_VERSION = 1;
14
+ /** Sources a definition may name, read as one union. Only `builtin:all` and `builtin:for_you` have none. */
15
+ export const FEED_SOURCES_MAX = 50;
16
+ /** The largest canonical definition the server keeps, in bytes. */
17
+ export const FEED_DEFINITION_MAX_BYTES = 16 * 1024;
18
+ export const FEED_SOURCE_KINDS = [
19
+ 'category', 'tag', 'account', 'community', 'collection', 'list', 'story',
20
+ 'bsky_feed', 'bsky_list', 'bsky_starterpack', 'nostr_set',
21
+ ];
22
+ export const FEED_RANKING_MODES = ['hot', 'new', 'top', 'for_you', 'viral'];
23
+ export const FEED_RANKING_RANGES = ['24h', '7d', '30d', '1y'];
24
+ export const FEED_MEDIA = ['any', 'images', 'video', 'longread'];
25
+ export const FEED_NETWORKS = ['minds', 'bluesky', 'activitypub', 'nostr'];
26
+ /** Source kinds a topical feed may hold (with a hot, new or top ranking); any other feed is 'wide'. */
27
+ export const FEED_TOPICAL_SOURCE_KINDS = ['category', 'tag', 'account', 'community', 'list', 'collection', 'story'];
28
+ export const FEED_TOPICAL_MODES = ['hot', 'new', 'top'];
29
+ /** The one field that names what each source kind reads. */
30
+ export const FEED_SOURCE_KEY = {
31
+ category: 'id',
32
+ tag: 'slug',
33
+ account: 'ref',
34
+ community: 'id',
35
+ collection: 'id',
36
+ list: 'id',
37
+ story: 'clusterId',
38
+ bsky_feed: 'uri',
39
+ bsky_list: 'uri',
40
+ bsky_starterpack: 'uri',
41
+ nostr_set: 'naddr',
42
+ };
43
+ /** The built-in feed for a Discover category. */
44
+ export function builtinCategoryFeedRef(category) {
45
+ return `builtin:category:${category}`;
46
+ }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './resources/discovery-learning.js';
2
2
  import { DiscoveryResource } from './resources/discovery.js';
3
3
  export * from './resources/discovery.js';
4
+ export * from './feed-definition.js';
4
5
  import { AuthResource } from './resources/auth.js';
5
6
  import { PostsResource } from './resources/posts.js';
6
7
  import { UsersResource } from './resources/users.js';
@@ -154,12 +155,12 @@ export { UsersResource } from './resources/users.js';
154
155
  export { CommunitiesResource } from './resources/communities.js';
155
156
  export { ChatResource } from './resources/chat.js';
156
157
  export { E2eeResource } from './resources/e2ee.js';
157
- export type { E2eeDevice, E2eeDevicesRealtimeEvent, E2eeEnvelope, E2eeEvent, E2eeHasDependentsDetails, E2eeKeyPackageStatus, E2eeLink, E2eeLinkCancelledBy, E2eeLinkProgress, E2eeLinkRealtimeEvent, E2eeLinkState, E2eeObjectDownload, E2eeObjectUpload, E2eeRealtimeEvent, E2eeRevokeResponse, E2eeStatus, E2eeStatusReason, } from './resources/e2ee.js';
158
+ export type { E2eeAccountReset, E2eeDevice, E2eeDevicesRealtimeEvent, E2eeEnvelope, E2eeEvent, E2eeHasDependentsDetails, E2eeKeyPackageStatus, E2eeLink, E2eeLinkCancelledBy, E2eeLinkProgress, E2eeLinkRealtimeEvent, E2eeLinkState, E2eeObjectDownload, E2eeObjectUpload, E2eeRealtimeEvent, E2eeResetCodeSent, E2eeResetErrorCode, E2eeRevokeResponse, E2eeStatus, E2eeStatusReason, } from './resources/e2ee.js';
158
159
  export { ProjectsResource } from './resources/projects.js';
159
160
  export { AgentsResource, SUPPORTED_MODELS } from './resources/agents.js';
160
161
  export { EvidenceResource } from './resources/evidence.js';
161
162
  export type { EvidenceTarget, EvalType, CreateEvalInput, SimulateInput, SimulateResult, EvalRunRow, EvalResultRow, EvalRunDetail, EvidenceSummary, EvidenceEvent, EvidenceRecordDetail } from './resources/evidence.js';
162
- export type { AgentMessage, AgentMessageInput, AgentInboxParams, SupportedModel, SalesLead, SalesLeadListParams, SalesLeadStatus } from './resources/agents.js';
163
+ export type { AgentMessage, AgentMessageInput, AgentInboxParams, AgentAskInput, AgentAskResult, SupportedModel, SalesLead, SalesLeadListParams, SalesLeadStatus } from './resources/agents.js';
163
164
  export { TagsResource } from './resources/tags.js';
164
165
  export { SandboxResource } from './resources/sandbox.js';
165
166
  export { ProfilesResource } from './resources/profiles.js';
@@ -173,6 +174,7 @@ export { InviteCodesResource } from './resources/invite-codes.js';
173
174
  export { InviteCodesAdminResource } from './resources/invite-codes-admin.js';
174
175
  export { AdminResource } from './resources/admin.js';
175
176
  export { EmailResource } from './resources/email.js';
177
+ export type { SendEmailInput, SendEmailResult, SendEmailMessage } from './resources/email.js';
176
178
  export { StorageResource } from './resources/storage.js';
177
179
  export { DatabasesResource } from './resources/databases.js';
178
180
  export { EnvVarsResource } from './resources/env-vars.js';
@@ -194,7 +196,7 @@ export type { CuratorSource, CuratorPrompt, CuratorRunInput, CuratorRunResult, C
194
196
  export { ReportsResource } from './resources/reports.js';
195
197
  export type { ReportTargetType, ReportStatus, CreateReportInput, ReportRecord, ResolveReportInput, } from './resources/reports.js';
196
198
  export { ModerationResource } from './resources/moderation.js';
197
- export type { ModerationTargetType, ModerationActionType, ModerationAppealStatus, ModerationPrinciple, PublicModerationAction, PublicModerationLog, OwnModerationAppeal, OwnModerationAction, OwnModerationLog, ApplyModerationActionInput, } from './resources/moderation.js';
199
+ export type { ModerationTargetType, ModerationActionType, ModerationAppealStatus, ModerationPrinciple, PublicModerationAction, PublicModerationLog, OwnModerationAppeal, OwnModerationAction, OwnModerationLog, ApplyModerationActionInput, AgentModerationMode, AgentModerationGrant, } from './resources/moderation.js';
198
200
  export { LinkPreviewResource } from './resources/link-preview.js';
199
201
  export { SEARCH_SECTIONS, SearchResource } from './resources/search.js';
200
202
  export type { SearchAnswer, SearchGroup, SearchOmitReason, SearchParams, SearchPerson, SearchRelated, SearchResponse, SearchSection, SearchStory, SearchTopic } from './resources/search.js';
@@ -214,8 +216,8 @@ export type { LinkedTokenWallet, PayoutState, TokenBalance, TokenLedgerEntry } f
214
216
  export { BoostsResource } from './resources/boosts.js';
215
217
  export type { BoostBalance, BoostBalanceResponse, BoostCampaign, BoostCampaignResponse, BoostEventResult, BoostLedgerEntry, BoostLedgerKind, BoostPlanCredit, BoostRejectionReason, BoostReviewStatus, BoostStatus, BoostTopupCheckout, BoostTopupConfirmation, BoostTopupLimits, } from './resources/boosts.js';
216
218
  export { ProtocolsResource } from './resources/protocols.js';
217
- export { PROTOCOL_ADAPTER_MATURITIES, PROTOCOL_CAPABILITY_OPERATIONS, PROTOCOL_CAPABILITY_STATUSES, } from './resources/protocols.js';
218
- export type { SocialProfile, SocialSubscription, SocialSubscriptionChange, SocialProfilePage, SocialRadar, SocialRadarCluster, SocialRadarMember, SocialRadarParams, SocialRadarPosts, SocialRadarStory, SocialRadarStoryArchive, SocialNetwork, SocialPost, SocialConversation, SocialTrend, SocialTrendProvenance, SocialTrends, SocialTrendSourceIndex, SocialTrendFeed, SocialPopularProfiles, SocialAuthorFeed, SocialFollowingFeed, SocialFollowingSource, SearchPublicProfilesParams, SearchPublicPostsParams, SocialPostSearch, HostedProtocolConnections, HostedProtocol, HostedProtocolIdentity, HostedNostrChallenge, HostedNostrIdentityProof, NativeNostrPrepareInput, NativeNostrPrepared, NativeNostrAccount, NativeNostrPostState, NativeNostrReceipt, NativeSocialProtocol, FederationIdentity, FederationIdentityView, NativeSocialAccount, NativeSocialCallbackInput, NativeReplyPrepareInput, NativePostPrepareInput, NativeMediaInput, NativeMediaItem, NativePostBatch, NativePostHistory, NativeDelegatedPostHistoryItem, NativeNostrPostHistoryItem, NativeFollowSourceInput, NativeFollowPrepareInput, NativeFollowTarget, NativeFollowReceipt, NativeFollowState, NativeFollowAccount, NativeFollowStates, NativeFollowReview, NativeLikeSourceInput, NativeRepostSourceInput, NativeLikePrepareInput, NativeRepostPrepareInput, NativeLikeTarget, NativeRepostTarget, NativeLikeReceipt, NativeRepostReceipt, NativeLikeState, NativeRepostState, NativeLikeReview, NativeRepostReview, NativeReplyReceipt, NativeReplyBatch, NativeReplyHistory, NativeDelegatedReplyHistoryItem, NativeNostrReplyResult, NativeNostrReplyHistoryItem, NativeReplyRemovalReceipt, NativeReplyRemovalPreview, SocialSourceRef, SocialSourceControl, SocialSourceControlDisplay, SocialSourceControlChange, HostedPostPreview, ConnectHostedIdentityInput, CreateHostedIdentityInput, CreatedHostedProtocolIdentity, PreviewHostedPostInput, PublishHostedPostInput, ListProtocolCandidatesParams, ProtocolAdapterMaturity, ProtocolAdapterMetadata, ProtocolCandidateListResponse, ProtocolCandidatePageMeta, ProtocolCapabilityOperation, ProtocolCapabilityStatus, ProtocolCollectionStatus, ProtocolIngestionReplayResult, ProtocolIngestionStatus, ProtocolQuarantinedCandidate, ProtocolRefreshResult, ProtocolSettings, ProtocolSettingsUpdateResult, ReplayProtocolIngestionJobInput, UpdateSettingsInput as UpdateProtocolSettingsInput, } from './resources/protocols.js';
219
+ export { PROTOCOL_ADAPTER_MATURITIES, PROTOCOL_CAPABILITY_OPERATIONS, PROTOCOL_CAPABILITY_STATUSES, viralItemHasVideo, } from './resources/protocols.js';
220
+ export type { SocialProfile, SocialBridge, SocialSubscription, SocialSubscriptionChange, SocialProfilePage, SocialRadar, SocialRadarCluster, SocialRadarMember, SocialRadarParams, SocialRadarPosts, SocialRadarStory, SocialRadarStoryArchive, ViralBaseline, ViralItem, ViralItemFields, ViralItemSpread, ViralItemVelocity, ViralLabel, ViralMindsCard, ViralMindsItem, ViralNetwork, ViralOpenProtocol, ViralProtocol, ViralProvider, ViralReadMeta, ViralReadParams, ViralReadResponse, ViralReadStatus, ViralRef, ViralSocialItem, SocialNetwork, SocialPost, SocialConversation, SocialTrend, SocialTrendProvenance, SocialTrends, SocialTrendSourceIndex, SocialTrendFeed, SocialPopularProfiles, SocialAuthorFeed, SocialFollowingFeed, SocialFollowingSource, SearchPublicProfilesParams, SearchPublicPostsParams, SocialPostSearch, HostedProtocolConnections, HostedProtocol, HostedProtocolIdentity, HostedNostrChallenge, HostedNostrIdentityProof, NativeNostrPrepareInput, NativeNostrPrepared, NativeNostrAccount, NativeNostrPostState, NativeNostrReceipt, NativeSocialProtocol, FederationIdentity, FederationIdentityView, NativeSocialAccount, NativeSocialCallbackInput, NativeReplyPrepareInput, NativePostPrepareInput, NativeMediaInput, NativeMediaItem, NativePostBatch, NativePostHistory, NativeDelegatedPostHistoryItem, NativeNostrPostHistoryItem, NativeFollowSourceInput, NativeFollowPrepareInput, NativeFollowTarget, NativeFollowReceipt, NativeFollowState, NativeFollowAccount, NativeFollowStates, NativeFollowReview, NativeLikeSourceInput, NativeRepostSourceInput, NativeLikePrepareInput, NativeRepostPrepareInput, NativeLikeTarget, NativeRepostTarget, NativeLikeReceipt, NativeRepostReceipt, NativeLikeState, NativeRepostState, NativeLikeReview, NativeRepostReview, NativeReplyReceipt, NativeReplyBatch, NativeReplyHistory, NativeDelegatedReplyHistoryItem, NativeNostrReplyResult, NativeNostrReplyHistoryItem, NativeReplyRemovalReceipt, NativeReplyRemovalPreview, SocialSourceRef, SocialSourceControl, SocialSourceControlDisplay, SocialSourceControlChange, HostedPostPreview, ConnectHostedIdentityInput, CreateHostedIdentityInput, CreatedHostedProtocolIdentity, PreviewHostedPostInput, PublishHostedPostInput, ListProtocolCandidatesParams, ProtocolAdapterMaturity, ProtocolAdapterMetadata, ProtocolCandidateListResponse, ProtocolCandidatePageMeta, ProtocolCapabilityOperation, ProtocolCapabilityStatus, ProtocolCollectionStatus, ProtocolIngestionReplayResult, ProtocolIngestionStatus, ProtocolQuarantinedCandidate, ProtocolRefreshResult, ProtocolSettings, ProtocolSettingsUpdateResult, ReplayProtocolIngestionJobInput, UpdateSettingsInput as UpdateProtocolSettingsInput, } from './resources/protocols.js';
219
221
  export { InboxResource } from './resources/inbox.js';
220
222
  export { NetworkResource } from './resources/network.js';
221
223
  export { SimulatorResource } from './resources/simulator.js';
@@ -240,7 +242,7 @@ export { TemplatesResource } from './resources/templates.js';
240
242
  export type { Template, CreateTemplateInput, UpdateTemplateInput, ListTemplatesParams } from './resources/templates.js';
241
243
  export { MediaResource } from './resources/media.js';
242
244
  export type { GenerateImageInput, GeneratedImage, ImageProvider } from './resources/media.js';
243
- export { RecursivError, AuthenticationError, AuthorizationError, LegacyHandoffError, NotFoundError, ValidationError, InsufficientCreditsError, RateLimitError, ConflictError, isActionRateLimitScope, } from './errors.js';
245
+ export { RecursivError, AuthenticationError, AuthorizationError, LegacyHandoffError, NotFoundError, ValidationError, InsufficientCreditsError, RateLimitError, ConflictError, isActionRateLimitScope, EmailNotSentError, } from './errors.js';
244
246
  export type { RateLimitDetails } from './errors.js';
245
247
  export { parseSSE } from './lib/sse.js';
246
248
  export * from './lib/webhooks.js';
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './resources/discovery-learning.js';
2
2
  import { DiscoveryResource } from './resources/discovery.js';
3
3
  export * from './resources/discovery.js';
4
+ export * from './feed-definition.js';
4
5
  import { HttpClient } from './client.js';
5
6
  import { AuthResource } from './resources/auth.js';
6
7
  import { PostsResource } from './resources/posts.js';
@@ -261,7 +262,7 @@ export { UploadsResource } from './resources/uploads.js';
261
262
  export { WalletResource } from './resources/wallet.js';
262
263
  export { BoostsResource } from './resources/boosts.js';
263
264
  export { ProtocolsResource } from './resources/protocols.js';
264
- export { PROTOCOL_ADAPTER_MATURITIES, PROTOCOL_CAPABILITY_OPERATIONS, PROTOCOL_CAPABILITY_STATUSES, } from './resources/protocols.js';
265
+ export { PROTOCOL_ADAPTER_MATURITIES, PROTOCOL_CAPABILITY_OPERATIONS, PROTOCOL_CAPABILITY_STATUSES, viralItemHasVideo, } from './resources/protocols.js';
265
266
  export { InboxResource } from './resources/inbox.js';
266
267
  export { NetworkResource } from './resources/network.js';
267
268
  export { SimulatorResource } from './resources/simulator.js';
@@ -277,6 +278,6 @@ export { HumanInputResource } from './resources/human-input.js';
277
278
  export { SwarmsResource } from './resources/swarms.js';
278
279
  export { TemplatesResource } from './resources/templates.js';
279
280
  export { MediaResource } from './resources/media.js';
280
- export { RecursivError, AuthenticationError, AuthorizationError, LegacyHandoffError, NotFoundError, ValidationError, InsufficientCreditsError, RateLimitError, ConflictError, isActionRateLimitScope, } from './errors.js';
281
+ export { RecursivError, AuthenticationError, AuthorizationError, LegacyHandoffError, NotFoundError, ValidationError, InsufficientCreditsError, RateLimitError, ConflictError, isActionRateLimitScope, EmailNotSentError, } from './errors.js';
281
282
  export { parseSSE } from './lib/sse.js';
282
283
  export * from './lib/webhooks.js';
@@ -1,6 +1,7 @@
1
1
  import type { Socket } from 'socket.io-client';
2
2
  import { HttpClient } from './client.js';
3
3
  import type { E2eeDevicesRealtimeEvent, E2eeLinkRealtimeEvent, E2eeRealtimeEvent } from './resources/e2ee.js';
4
+ import type { ChatConversationEvent, ChatMembersEvent } from './types.js';
4
5
  export interface ChatMessageEvent {
5
6
  id: string;
6
7
  conversationId: string;
@@ -147,7 +148,8 @@ export declare class RealtimeClient {
147
148
  *
148
149
  * Server events include `notification`, `feed_update`,
149
150
  * `conversation_created`, `chat_message`, `chat_typing`, `agent_thinking`,
150
- * `e2ee:event`, `e2ee:link` and `e2ee:devices`.
151
+ * `chat:members`, `chat:conversation`, `e2ee:event`, `e2ee:link` and
152
+ * `e2ee:devices`.
151
153
  */
152
154
  on<T = unknown>(event: string, listener: (payload: T) => void): () => void;
153
155
  /** Join a conversation room now, and again after every reconnect, until you leave it. */
@@ -159,6 +161,14 @@ export declare class RealtimeClient {
159
161
  onMessageDelete(callback: (msg: ChatMessageDeleteEvent) => void): (() => void) | undefined;
160
162
  onTyping(callback: (event: TypingEvent) => void): (() => void) | undefined;
161
163
  onAgentThinking(callback: (event: AgentThinkingEvent) => void): (() => void) | undefined;
164
+ /**
165
+ * A private group's people changed (0.7.59): `{ conversationId, change, userIds, actorId }`,
166
+ * change `added`, `removed`, `left` or `invites_cancelled`. Sent to everyone in the group
167
+ * and to the people it is about. Read the conversation again; in an encrypted group, check its keys.
168
+ */
169
+ onChatMembers(callback: (event: ChatMembersEvent) => void): () => void;
170
+ /** A private group was renamed (0.7.59): `{ conversationId, change: 'renamed', name, actorId }`. */
171
+ onChatConversation(callback: (event: ChatConversationEvent) => void): () => void;
162
172
  /**
163
173
  * The E2EE doorbell after each append to an encrypted conversation this
164
174
  * account belongs to: `{ conversationId, seq }`, plus the stored `event`
package/dist/realtime.js CHANGED
@@ -369,7 +369,8 @@ export class RealtimeClient {
369
369
  *
370
370
  * Server events include `notification`, `feed_update`,
371
371
  * `conversation_created`, `chat_message`, `chat_typing`, `agent_thinking`,
372
- * `e2ee:event`, `e2ee:link` and `e2ee:devices`.
372
+ * `chat:members`, `chat:conversation`, `e2ee:event`, `e2ee:link` and
373
+ * `e2ee:devices`.
373
374
  */
374
375
  on(event, listener) {
375
376
  // Every call is its own subscription, even for a function that is already
@@ -426,6 +427,18 @@ export class RealtimeClient {
426
427
  onAgentThinking(callback) {
427
428
  return this.on('agent_thinking', callback);
428
429
  }
430
+ /**
431
+ * A private group's people changed (0.7.59): `{ conversationId, change, userIds, actorId }`,
432
+ * change `added`, `removed`, `left` or `invites_cancelled`. Sent to everyone in the group
433
+ * and to the people it is about. Read the conversation again; in an encrypted group, check its keys.
434
+ */
435
+ onChatMembers(callback) {
436
+ return this.on('chat:members', callback);
437
+ }
438
+ /** A private group was renamed (0.7.59): `{ conversationId, change: 'renamed', name, actorId }`. */
439
+ onChatConversation(callback) {
440
+ return this.on('chat:conversation', callback);
441
+ }
429
442
  /**
430
443
  * The E2EE doorbell after each append to an encrypted conversation this
431
444
  * account belongs to: `{ conversationId, seq }`, plus the stored `event`
@@ -26,6 +26,68 @@ export interface AgentInboxParams {
26
26
  limit?: number;
27
27
  offset?: number;
28
28
  }
29
+ export interface AgentAskInput {
30
+ organization_id: string;
31
+ /** The person whose agent you are asking: name, first name, @username, email or user id. */
32
+ owner: string;
33
+ question: string;
34
+ /** How far back to read their record (1-90, default 7). */
35
+ since_days?: number;
36
+ /** false = read the record only, leave nothing in their agent's inbox. */
37
+ deliver?: boolean;
38
+ }
39
+ export interface AgentAskResult {
40
+ owner: {
41
+ id: string;
42
+ name: string | null;
43
+ username: string | null;
44
+ };
45
+ agents: Array<{
46
+ id: string;
47
+ name: string;
48
+ client: string | null;
49
+ }>;
50
+ window: {
51
+ since: string;
52
+ days: number;
53
+ };
54
+ record: {
55
+ claims: Array<{
56
+ task_id: string;
57
+ task_title: string;
58
+ task_status: string;
59
+ agent: string;
60
+ claim_status: string;
61
+ claimed_at: string;
62
+ completed_at: string | null;
63
+ released_at: string | null;
64
+ release_reason: string | null;
65
+ notes: string | null;
66
+ context_handoff: string | null;
67
+ pr_urls: string[] | null;
68
+ commits: string[] | null;
69
+ }>;
70
+ decisions: Array<{
71
+ id: string;
72
+ decision: string;
73
+ context: string | null;
74
+ tags: string[] | null;
75
+ project_id: string | null;
76
+ created_at: string;
77
+ }>;
78
+ };
79
+ question: {
80
+ delivered: true;
81
+ message_id: string;
82
+ to_agent_id: string;
83
+ to_agent_name: string;
84
+ from_agent_id: string;
85
+ } | {
86
+ delivered: false;
87
+ reason: string;
88
+ };
89
+ how_to_answer: string;
90
+ }
29
91
  export interface AgentLeaderboardParams extends PaginationParams {
30
92
  organization_id?: string;
31
93
  }
@@ -264,6 +326,14 @@ export declare class AgentsResource {
264
326
  }>>;
265
327
  /** Send a direct message to an agent */
266
328
  sendMessage(toAgentId: string, input: AgentMessageInput): Promise<SingleResponse<AgentMessage>>;
329
+ /**
330
+ * Ask a teammate's agent by naming its owner ("bill", "@ottman", an email).
331
+ * Returns that person's agents' work in the organization over the window
332
+ * (task claims with notes, handoffs, PRs and commits; decisions) and leaves
333
+ * the question in their agent's inbox; its reply arrives in yours as a
334
+ * `result` message with `metadata.in_reply_to`.
335
+ */
336
+ ask(input: AgentAskInput): Promise<SingleResponse<AgentAskResult>>;
267
337
  /** Get an agent's inbox (messages sent to them) */
268
338
  inbox(agentId: string, params?: AgentInboxParams): Promise<SingleResponse<AgentMessage[]>>;
269
339
  /** Get unread message count for an agent */
@@ -172,6 +172,16 @@ export class AgentsResource {
172
172
  sendMessage(toAgentId, input) {
173
173
  return this.client.post(`/agents/${toAgentId}/messages`, input);
174
174
  }
175
+ /**
176
+ * Ask a teammate's agent by naming its owner ("bill", "@ottman", an email).
177
+ * Returns that person's agents' work in the organization over the window
178
+ * (task claims with notes, handoffs, PRs and commits; decisions) and leaves
179
+ * the question in their agent's inbox; its reply arrives in yours as a
180
+ * `result` message with `metadata.in_reply_to`.
181
+ */
182
+ ask(input) {
183
+ return this.client.post('/agents/ask', input);
184
+ }
175
185
  /** Get an agent's inbox (messages sent to them) */
176
186
  inbox(agentId, params) {
177
187
  return this.client.get(`/agents/${agentId}/inbox`, params);