@recursiv/sdk 0.7.81 → 0.7.82
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 +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/resources/chat.d.ts +73 -1
- package/dist/resources/chat.js +83 -1
- package/dist/resources/network.d.ts +6 -0
- package/dist/resources/reports.d.ts +24 -0
- package/dist/resources/reports.js +12 -0
- package/llm.md +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -98,7 +98,7 @@ for await (const chunk of r.agents.chatStream(agent.id, { message: 'Hello!' }))
|
|
|
98
98
|
| `r.bookmarks` | `save`, `unsave`, `posts`, `list`, `keys`, `merge` — the member's saved posts, open-network posts and articles, synced across devices; `collections`: `list`, `create`, `update`, `remove`, `add`, `removeItem`, `items`, `posts` — private named collections of saves (0.7.68, where `network.getConfig()` advertises `capabilities.bookmark_collections`) |
|
|
99
99
|
| `r.feeds` | `top` (what the member is most likely to engage with, rotated by what they saw, with open-network lanes and the lead story), `stories` (the story tail), `publicTop` (a visitor's top, keyless and edge-cacheable) |
|
|
100
100
|
| `r.communities` | `create`, `join`, `search`, `members` |
|
|
101
|
-
| `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) |
|
|
101
|
+
| `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); photos and voice notes: `uploadAttachment`, `signAttachments` (private chat storage, 0.7.82) |
|
|
102
102
|
| `r.tags` | `create`, `list` |
|
|
103
103
|
| `r.signals` | `batch` (up to 100 engagement signals, such as views, dwell and hides, for the member's own ranking; `keepalive` for a page-leave flush), `record` (one signal) (0.7.71) |
|
|
104
104
|
| `r.curator` | `today` (World Today; a world story can carry `story_key` and `discussion`, its count across networks), `storyPosts` / `memberStoryPosts` (one page of a story's posts, keyless or under the member's key), `storyPostPages` (walk every page), `forYou`, `run`, `refreshIfStale`, `seedDeck` |
|
package/dist/index.d.ts
CHANGED
|
@@ -165,7 +165,8 @@ export { POSTS_BATCH_MAX, PostsResource } from './resources/posts.js';
|
|
|
165
165
|
export type { CategoryOrder, CategoryOrderMeta, CategoryOrderReason, PostBatch, PostBatchItem } from './resources/posts.js';
|
|
166
166
|
export { UsersResource } from './resources/users.js';
|
|
167
167
|
export { CommunitiesResource } from './resources/communities.js';
|
|
168
|
-
export { ChatResource } from './resources/chat.js';
|
|
168
|
+
export { ChatResource, CHAT_ATTACHMENT_REF_PREFIX, chatAttachmentKeysIn, chatAttachmentRefsIn } from './resources/chat.js';
|
|
169
|
+
export type { ChatAttachmentRef, ChatAttachmentUploadInput, ChatAttachmentUploadUrl, ChatAttachmentUploadUrlInput, SignedChatAttachment, } from './resources/chat.js';
|
|
169
170
|
export { E2eeResource } from './resources/e2ee.js';
|
|
170
171
|
export type { E2eeAccountReset, E2eeDevice, E2eeDevicesRealtimeEvent, E2eeEnvelope, E2eeEvent, E2eeHasDependentsDetails, E2eeKeyPackageStatus, E2eeLink, E2eeLinkCancelledBy, E2eeLinkProgress, E2eeLinkRealtimeEvent, E2eeLinkState, E2eeObjectDownload, E2eeObjectUpload, E2eeRealtimeEvent, E2eeResetCodeSent, E2eeResetErrorCode, E2eeRevokeResponse, E2eeStartRequest, E2eeStatus, E2eeStatusReason, } from './resources/e2ee.js';
|
|
171
172
|
export { ProjectsResource } from './resources/projects.js';
|
|
@@ -207,7 +208,7 @@ export type { AppSubscriptionBoostCredit, AppSubscriptionCheckoutResult, AppSubs
|
|
|
207
208
|
export type { CuratorSource, CuratorPrompt, CuratorRunInput, CuratorRunResult, CuratorTodayEdition, CuratorTodayExcerpt, CuratorTodayLeadImage, CuratorTodayParams, CuratorTodayRadar, CuratorTodayReaction, CuratorTodayResponse, CuratorTodaySource, CuratorTodayStory, CuratorTodayDiscussion, CuratorStoryDiscussion, CuratorStoryLaneOutcome, CuratorStoryMindsPost, CuratorStoryPostItem, CuratorStoryPostPagesOptions, CuratorStoryPostsPage, CuratorStoryPostsParams, CuratorStoryReader, CuratorStorySocialPost, CuratorStoryVolumeLanes, CuratorStoryVolumeMeta, StoryPostNetwork, StoryPostPool, StoryPostSort, ForYouMeta, ForYouParams, ForYouSurface, ForYouWorldBlock, ForYouWorldBlockType, ForYouWorldCategoryShortcut, ForYouWorldItem, ForYouWorldMeta, ForYouWorldParams, ForYouWorldPart, ForYouWorldResponse, ForYouWorldStory, ForYouWorldStoryTarget, ForYouWorldViral, } from './resources/curator.js';
|
|
208
209
|
export { STORY_POOL_MAX_POSTS, STORY_POST_NETWORKS, STORY_POSTS_PAGE_MAX } from './resources/curator.js';
|
|
209
210
|
export { ReportsResource } from './resources/reports.js';
|
|
210
|
-
export type { ReportTargetType, ReportStatus, CreateReportInput, ReportRecord, ResolveReportInput, } from './resources/reports.js';
|
|
211
|
+
export type { ReportTargetType, ReportStatus, CreateReportInput, ReportRecord, ResolveReportInput, ReportedMessageAttachment, ReportedMessageAttachments, } from './resources/reports.js';
|
|
211
212
|
export { JudgmentsResource, isJudgmentSharedWordsError } from './resources/judgments.js';
|
|
212
213
|
export type { JudgmentSubjectKind, JudgmentSource, JudgmentOverrideMethod, PostLabelsStatus, PostLabelsQuery, PostLabelsSubject, PostLabelsCategory, PostLabelsPolitics, PostJudgmentRecord, PostJudgment, PostSafetyAttribution, PostLabelsCategoryView, PostLabelsSummaryView, PostLabelsFullView, PostLabels, DisputeJudgmentInput, JudgmentDispute, ReviewJudgmentInput, JudgmentReviewUpheld, JudgmentReviewAwaitingReviewer, JudgmentReviewOverridden, JudgmentReview, JudgmentSharedWordsDetails, JudgmentSharedWordsError, } from './resources/judgments.js';
|
|
213
214
|
export { ModerationResource } from './resources/moderation.js';
|
package/dist/index.js
CHANGED
|
@@ -236,7 +236,7 @@ export { AuthResource } from './resources/auth.js';
|
|
|
236
236
|
export { POSTS_BATCH_MAX, PostsResource } from './resources/posts.js';
|
|
237
237
|
export { UsersResource } from './resources/users.js';
|
|
238
238
|
export { CommunitiesResource } from './resources/communities.js';
|
|
239
|
-
export { ChatResource } from './resources/chat.js';
|
|
239
|
+
export { ChatResource, CHAT_ATTACHMENT_REF_PREFIX, chatAttachmentKeysIn, chatAttachmentRefsIn } from './resources/chat.js';
|
|
240
240
|
export { E2eeResource } from './resources/e2ee.js';
|
|
241
241
|
export { ProjectsResource } from './resources/projects.js';
|
|
242
242
|
export { AgentsResource, SUPPORTED_MODELS, AGENT_DIRECTORY_SORTS, AGENT_DIRECTORY_MAX_LIMIT } from './resources/agents.js';
|
package/dist/resources/chat.d.ts
CHANGED
|
@@ -116,7 +116,11 @@ export declare class ChatResource {
|
|
|
116
116
|
type: string;
|
|
117
117
|
};
|
|
118
118
|
}>>;
|
|
119
|
-
/**
|
|
119
|
+
/**
|
|
120
|
+
* Edit a message's words (only the sender can edit). Keep each `chat-attachment:` reference it carries as it is: the
|
|
121
|
+
* server refuses an edit that drops, adds or swaps one (400 `attachment_refs_changed`, 0.7.82). To take an attachment
|
|
122
|
+
* back, delete the message.
|
|
123
|
+
*/
|
|
120
124
|
editMessage(messageId: string, input: {
|
|
121
125
|
content: string;
|
|
122
126
|
}): Promise<SingleResponse<Message>>;
|
|
@@ -130,4 +134,72 @@ export declare class ChatResource {
|
|
|
130
134
|
unreadCount(conversationId: string): Promise<SingleResponse<{
|
|
131
135
|
unread_count: number;
|
|
132
136
|
}>>;
|
|
137
|
+
/**
|
|
138
|
+
* A PUT URL for one photo or voice note to send in a plaintext chat (0.7.82). With the server's private chat
|
|
139
|
+
* storage on, `private` is true, the URL writes into a private bucket and `ref` is `chat-attachment:<key>`, the text
|
|
140
|
+
* to send; with it off, `ref` is the upload's public URL. An end-to-end encrypted chat answers 409
|
|
141
|
+
* `conversation_encrypted`: its attachments go through `r.e2ee`. Most callers want `uploadAttachment`.
|
|
142
|
+
*/
|
|
143
|
+
attachmentUploadUrl(conversationId: string, input: ChatAttachmentUploadUrlInput): Promise<SingleResponse<ChatAttachmentUploadUrl>>;
|
|
144
|
+
/**
|
|
145
|
+
* Upload one photo or voice note for a plaintext chat end to end and resolve the text to send for it (0.7.82): read
|
|
146
|
+
* the bytes, get the URL, PUT them with the matching Content-Type, and reject a failed transfer. Send `ref` as the
|
|
147
|
+
* message (or within it): a private reference renders through `signAttachments`, a public URL as before.
|
|
148
|
+
*/
|
|
149
|
+
uploadAttachment(conversationId: string, input: ChatAttachmentUploadInput): Promise<ChatAttachmentUploadUrl>;
|
|
150
|
+
/**
|
|
151
|
+
* Short-lived URLs for a conversation's private attachments (0.7.82), at most 50 keys a call (the keys in its
|
|
152
|
+
* messages' `chat-attachment:` references; `chatAttachmentKeysIn` finds them). The server signs a key only for a
|
|
153
|
+
* member of the conversation, and only while a message its sender wrote there still carries it; any other key
|
|
154
|
+
* comes back with `url: null`. A URL works for about five minutes and is served `private, no-store`: ask again
|
|
155
|
+
* rather than keeping it.
|
|
156
|
+
*/
|
|
157
|
+
signAttachments(conversationId: string, keys: string[]): Promise<SingleResponse<{
|
|
158
|
+
attachments: SignedChatAttachment[];
|
|
159
|
+
}>>;
|
|
160
|
+
}
|
|
161
|
+
export interface ChatAttachmentUploadUrlInput {
|
|
162
|
+
/** image/jpeg, image/png, image/webp, image/gif, audio/mpeg, audio/mp4, audio/wav, audio/ogg or audio/webm. */
|
|
163
|
+
content_type: string;
|
|
164
|
+
/** The exact byte count the PUT will send (signed into the URL; at most 50 MB). */
|
|
165
|
+
content_length: number;
|
|
166
|
+
}
|
|
167
|
+
export interface ChatAttachmentUploadUrl {
|
|
168
|
+
/** True when the attachment goes to the server's private chat storage. */
|
|
169
|
+
private: boolean;
|
|
170
|
+
/** PUT the bytes here with the same Content-Type. */
|
|
171
|
+
upload_url: string;
|
|
172
|
+
key: string;
|
|
173
|
+
/** The text to send for this attachment: `chat-attachment:<key>` when private, else the public URL. */
|
|
174
|
+
ref: string;
|
|
175
|
+
}
|
|
176
|
+
export interface ChatAttachmentUploadInput {
|
|
177
|
+
/** Caller-held bytes, such as a browser File or React Native Blob. */
|
|
178
|
+
blob?: Blob;
|
|
179
|
+
/** A local URI that the SDK should read into a Blob first. */
|
|
180
|
+
uri?: string;
|
|
181
|
+
/** Defaults to blob.type. */
|
|
182
|
+
contentType?: string;
|
|
183
|
+
/** Optional transport override for React Native adapters and focused tests. */
|
|
184
|
+
fetchImpl?: typeof fetch;
|
|
185
|
+
}
|
|
186
|
+
export interface SignedChatAttachment {
|
|
187
|
+
key: string;
|
|
188
|
+
/** A GET URL valid until `expires_at`, or null when this caller may not open the key. */
|
|
189
|
+
url: string | null;
|
|
190
|
+
expires_at: string | null;
|
|
191
|
+
}
|
|
192
|
+
/** The text a message carries before a private chat attachment's key. */
|
|
193
|
+
export declare const CHAT_ATTACHMENT_REF_PREFIX = "chat-attachment:";
|
|
194
|
+
/** One private attachment a message's text refers to. */
|
|
195
|
+
export interface ChatAttachmentRef {
|
|
196
|
+
/** The whole reference as it appears in the text (`chat-attachment:<key>`). */
|
|
197
|
+
ref: string;
|
|
198
|
+
/** The key to pass to `signAttachments`. */
|
|
199
|
+
key: string;
|
|
200
|
+
kind: 'image' | 'audio';
|
|
133
201
|
}
|
|
202
|
+
/** The private attachments a message's text refers to, in order, each once (0.7.82). */
|
|
203
|
+
export declare function chatAttachmentRefsIn(content: string | null | undefined): ChatAttachmentRef[];
|
|
204
|
+
/** The private attachment keys a message's text refers to, for `signAttachments` (0.7.82). */
|
|
205
|
+
export declare function chatAttachmentKeysIn(content: string | null | undefined): string[];
|
package/dist/resources/chat.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RecursivError } from '../errors.js';
|
|
1
2
|
export class ChatResource {
|
|
2
3
|
client;
|
|
3
4
|
constructor(client) {
|
|
@@ -127,7 +128,11 @@ export class ChatResource {
|
|
|
127
128
|
reactToMessage(messageId, input) {
|
|
128
129
|
return this.client.post(`/chat/messages/${messageId}/react`, input);
|
|
129
130
|
}
|
|
130
|
-
/**
|
|
131
|
+
/**
|
|
132
|
+
* Edit a message's words (only the sender can edit). Keep each `chat-attachment:` reference it carries as it is: the
|
|
133
|
+
* server refuses an edit that drops, adds or swaps one (400 `attachment_refs_changed`, 0.7.82). To take an attachment
|
|
134
|
+
* back, delete the message.
|
|
135
|
+
*/
|
|
131
136
|
editMessage(messageId, input) {
|
|
132
137
|
return this.client.put(`/chat/messages/${messageId}`, input);
|
|
133
138
|
}
|
|
@@ -143,4 +148,81 @@ export class ChatResource {
|
|
|
143
148
|
unreadCount(conversationId) {
|
|
144
149
|
return this.client.get('/chat/unread-count', { conversation_id: conversationId });
|
|
145
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* A PUT URL for one photo or voice note to send in a plaintext chat (0.7.82). With the server's private chat
|
|
153
|
+
* storage on, `private` is true, the URL writes into a private bucket and `ref` is `chat-attachment:<key>`, the text
|
|
154
|
+
* to send; with it off, `ref` is the upload's public URL. An end-to-end encrypted chat answers 409
|
|
155
|
+
* `conversation_encrypted`: its attachments go through `r.e2ee`. Most callers want `uploadAttachment`.
|
|
156
|
+
*/
|
|
157
|
+
attachmentUploadUrl(conversationId, input) {
|
|
158
|
+
return this.client.post(`/chat/conversations/${conversationId}/attachments/upload-url`, input);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Upload one photo or voice note for a plaintext chat end to end and resolve the text to send for it (0.7.82): read
|
|
162
|
+
* the bytes, get the URL, PUT them with the matching Content-Type, and reject a failed transfer. Send `ref` as the
|
|
163
|
+
* message (or within it): a private reference renders through `signAttachments`, a public URL as before.
|
|
164
|
+
*/
|
|
165
|
+
async uploadAttachment(conversationId, input) {
|
|
166
|
+
const hasBlob = input.blob !== undefined;
|
|
167
|
+
const hasUri = typeof input.uri === 'string' && input.uri.length > 0;
|
|
168
|
+
if (hasBlob === hasUri)
|
|
169
|
+
throw attachmentError(0, 'Provide exactly one of blob or uri.', 'invalid_upload_source');
|
|
170
|
+
const doFetch = input.fetchImpl ?? fetch;
|
|
171
|
+
let blob = input.blob;
|
|
172
|
+
if (!blob && input.uri) {
|
|
173
|
+
const source = await doFetch(input.uri);
|
|
174
|
+
if (!source.ok)
|
|
175
|
+
throw attachmentError(source.status, `Could not read upload source (HTTP ${source.status}).`, 'upload_source_failed');
|
|
176
|
+
blob = await source.blob();
|
|
177
|
+
}
|
|
178
|
+
if (!blob)
|
|
179
|
+
throw attachmentError(0, 'Upload source did not produce any bytes.', 'empty_upload_source');
|
|
180
|
+
const contentType = input.contentType?.trim() || blob.type?.trim();
|
|
181
|
+
if (!contentType)
|
|
182
|
+
throw attachmentError(0, 'A content type is required for chat attachments.', 'missing_content_type');
|
|
183
|
+
const minted = await this.attachmentUploadUrl(conversationId, { content_type: contentType, content_length: blob.size });
|
|
184
|
+
if (!minted?.data?.upload_url || !minted.data.ref) {
|
|
185
|
+
throw attachmentError(0, 'The API did not return a chat attachment upload URL.', 'missing_upload_url');
|
|
186
|
+
}
|
|
187
|
+
const response = await doFetch(minted.data.upload_url, { method: 'PUT', body: blob, headers: { 'Content-Type': contentType } });
|
|
188
|
+
if (!response.ok)
|
|
189
|
+
throw attachmentError(response.status, `Chat attachment upload failed (HTTP ${response.status}).`, 'chat_attachment_upload_failed');
|
|
190
|
+
return minted.data;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Short-lived URLs for a conversation's private attachments (0.7.82), at most 50 keys a call (the keys in its
|
|
194
|
+
* messages' `chat-attachment:` references; `chatAttachmentKeysIn` finds them). The server signs a key only for a
|
|
195
|
+
* member of the conversation, and only while a message its sender wrote there still carries it; any other key
|
|
196
|
+
* comes back with `url: null`. A URL works for about five minutes and is served `private, no-store`: ask again
|
|
197
|
+
* rather than keeping it.
|
|
198
|
+
*/
|
|
199
|
+
signAttachments(conversationId, keys) {
|
|
200
|
+
return this.client.post(`/chat/conversations/${conversationId}/attachments/sign`, { keys });
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function attachmentError(status, message, code) {
|
|
204
|
+
return new RecursivError(status, { type: 'upload_error', message, code });
|
|
205
|
+
}
|
|
206
|
+
/** The text a message carries before a private chat attachment's key. */
|
|
207
|
+
export const CHAT_ATTACHMENT_REF_PREFIX = 'chat-attachment:';
|
|
208
|
+
const CHAT_ATTACHMENT_REF_RE = /chat-attachment:(chat\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.([a-z0-9]{2,5}))/g;
|
|
209
|
+
/** The extensions the server mints a private attachment key with (and jpeg), as it parses one; anything else is text. */
|
|
210
|
+
const IMAGE_EXTENSIONS = new Set(['jpg', 'jpeg', 'png', 'webp', 'gif']);
|
|
211
|
+
const AUDIO_EXTENSIONS = new Set(['mp3', 'm4a', 'wav', 'ogg', 'weba']);
|
|
212
|
+
/** The private attachments a message's text refers to, in order, each once (0.7.82). */
|
|
213
|
+
export function chatAttachmentRefsIn(content) {
|
|
214
|
+
if (!content?.includes(CHAT_ATTACHMENT_REF_PREFIX))
|
|
215
|
+
return [];
|
|
216
|
+
const found = new Map();
|
|
217
|
+
for (const match of content.matchAll(CHAT_ATTACHMENT_REF_RE)) {
|
|
218
|
+
const extension = match[2];
|
|
219
|
+
const kind = AUDIO_EXTENSIONS.has(extension) ? 'audio' : IMAGE_EXTENSIONS.has(extension) ? 'image' : null;
|
|
220
|
+
if (kind && !found.has(match[1]))
|
|
221
|
+
found.set(match[1], { ref: match[0], key: match[1], kind });
|
|
222
|
+
}
|
|
223
|
+
return [...found.values()];
|
|
224
|
+
}
|
|
225
|
+
/** The private attachment keys a message's text refers to, for `signAttachments` (0.7.82). */
|
|
226
|
+
export function chatAttachmentKeysIn(content) {
|
|
227
|
+
return chatAttachmentRefsIn(content).map((attachment) => attachment.key);
|
|
146
228
|
}
|
|
@@ -11,10 +11,16 @@ interface NetworkConfig {
|
|
|
11
11
|
* `bookmark_collections` (0.7.68; absent on older servers): this server serves bookmark collections
|
|
12
12
|
* (`bookmarks.collections`). Show collections only when it is true, and still treat a 503
|
|
13
13
|
* `lists_unavailable` as off.
|
|
14
|
+
*
|
|
15
|
+
* `child_safety_report_category` (absent on older servers): this server files the child-safety report category's
|
|
16
|
+
* sub-types (`child_safety:minor_in_danger`, `:sexualised_minor`, `:grooming_enticement`, `:trafficking`) as
|
|
17
|
+
* urgent: top severity, an immediate staff alert, decided by a person. Offer them only when it is true; otherwise
|
|
18
|
+
* report child sexual abuse material as `csam`, which every server files as urgent.
|
|
14
19
|
*/
|
|
15
20
|
capabilities: {
|
|
16
21
|
ws_token: boolean;
|
|
17
22
|
bookmark_collections?: boolean;
|
|
23
|
+
child_safety_report_category?: boolean;
|
|
18
24
|
};
|
|
19
25
|
auth_methods: string;
|
|
20
26
|
default_template_name: string | null;
|
|
@@ -57,4 +57,28 @@ export declare class ReportsResource {
|
|
|
57
57
|
dismiss(reportId: string): Promise<SingleResponse<{
|
|
58
58
|
success: true;
|
|
59
59
|
}>>;
|
|
60
|
+
/**
|
|
61
|
+
* Short-lived URLs for the private chat photos and voice notes a reported message carries (0.7.82), for the staff
|
|
62
|
+
* person reviewing the report. A live admin's own key only: an AI account or an agent key gets 403
|
|
63
|
+
* `human_required`. Only the reported message's own attachments are signed; each URL works for about five minutes
|
|
64
|
+
* and is served `private, no-store`, so ask again rather than keeping it. A report of anything but a message is
|
|
65
|
+
* 400 `not_a_message_report`. Only a recipient's report opens anything: a report you filed yourself is 403
|
|
66
|
+
* `own_report`, and one not filed by a person in that chat (other than the message's sender) is 403
|
|
67
|
+
* `reporter_not_a_recipient`.
|
|
68
|
+
*/
|
|
69
|
+
signAttachments(reportId: string): Promise<SingleResponse<ReportedMessageAttachments>>;
|
|
70
|
+
}
|
|
71
|
+
export interface ReportedMessageAttachment {
|
|
72
|
+
key: string;
|
|
73
|
+
kind: 'image' | 'audio';
|
|
74
|
+
content_type: string;
|
|
75
|
+
/** A GET URL valid until `expires_at`. */
|
|
76
|
+
url: string;
|
|
77
|
+
expires_at: string;
|
|
78
|
+
}
|
|
79
|
+
export interface ReportedMessageAttachments {
|
|
80
|
+
report_id: string;
|
|
81
|
+
message_id: string;
|
|
82
|
+
conversation_id: string;
|
|
83
|
+
attachments: ReportedMessageAttachment[];
|
|
60
84
|
}
|
|
@@ -27,4 +27,16 @@ export class ReportsResource {
|
|
|
27
27
|
dismiss(reportId) {
|
|
28
28
|
return this.client.post(`/reports/${encodeURIComponent(reportId)}/dismiss`);
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Short-lived URLs for the private chat photos and voice notes a reported message carries (0.7.82), for the staff
|
|
32
|
+
* person reviewing the report. A live admin's own key only: an AI account or an agent key gets 403
|
|
33
|
+
* `human_required`. Only the reported message's own attachments are signed; each URL works for about five minutes
|
|
34
|
+
* and is served `private, no-store`, so ask again rather than keeping it. A report of anything but a message is
|
|
35
|
+
* 400 `not_a_message_report`. Only a recipient's report opens anything: a report you filed yourself is 403
|
|
36
|
+
* `own_report`, and one not filed by a person in that chat (other than the message's sender) is 403
|
|
37
|
+
* `reporter_not_a_recipient`.
|
|
38
|
+
*/
|
|
39
|
+
signAttachments(reportId) {
|
|
40
|
+
return this.client.post(`/reports/${encodeURIComponent(reportId)}/attachments/sign`);
|
|
41
|
+
}
|
|
30
42
|
}
|
package/llm.md
CHANGED
|
@@ -504,7 +504,9 @@ const { data: group } = await r.chat.createGroup({ name: 'Team', member_ids: ['u
|
|
|
504
504
|
const { data: msgs } = await r.chat.messages(dm.id, { limit: 50 })
|
|
505
505
|
```
|
|
506
506
|
|
|
507
|
-
Methods: `conversations`, `communityConversation`, `conversation`, `messages`, `send`, `dm`, `createGroup`, `addMembers`, `removeMember`, `updateGroup`, `deleteConversation`, `leave`, `acceptRequest`, `declineRequest`, `reactToMessage`, `editMessage`, `deleteMessage`, `markAsRead`, `unreadCount`
|
|
507
|
+
Methods: `conversations`, `communityConversation`, `conversation`, `messages`, `send`, `dm`, `createGroup`, `addMembers`, `removeMember`, `updateGroup`, `deleteConversation`, `leave`, `acceptRequest`, `declineRequest`, `reactToMessage`, `editMessage`, `deleteMessage`, `markAsRead`, `unreadCount`, `attachmentUploadUrl`, `uploadAttachment`, `signAttachments`
|
|
508
|
+
|
|
509
|
+
Chat photos and voice notes (0.7.82): `const { ref } = await r.chat.uploadAttachment(dm.id, { blob })`, then send `ref`. With the server's private chat storage on, `ref` is `chat-attachment:<key>`: render it with `(await r.chat.signAttachments(dm.id, chatAttachmentKeysIn(message.content))).data.attachments` (URLs live about five minutes, `private, no-store`; `url: null` for a key the caller may not open). `editMessage` changes a message's words only: an edit that drops, adds or swaps a `chat-attachment:` reference gets 400 `attachment_refs_changed` (delete the message instead). Otherwise `ref` is a public URL, as before. A group's chat tied to a community always gets a public URL. Staff reviewing a member's report of a message open its private attachments with `r.reports.signAttachments(reportId)` (a live admin's own key; an AI account or agent key gets 403 `human_required`; only a report filed by a person in that chat, other than the sender and the caller, opens anything: 403 `own_report` or `reporter_not_a_recipient` otherwise).
|
|
508
510
|
|
|
509
511
|
Scroll back with `messages(id, { cursor: page.meta.next_cursor })`, not a growing `offset`. Conversations carry `can_delete` / `can_leave`; check them before offering Delete or Leave.
|
|
510
512
|
|