@playdrop/playdrop-cli 0.16.11 → 0.16.16
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/config/client-meta.json +2 -2
- package/dist/commands/chat.d.ts +0 -7
- package/dist/commands/chat.js +40 -77
- package/dist/commands/worker/provider-telemetry.js +1 -1
- package/dist/commands/worker/runtime.js +2 -3
- package/dist/commands/worker.js +1 -1
- package/dist/index.js +0 -9
- package/node_modules/@playdrop/api-client/dist/client.d.ts +73 -16
- package/node_modules/@playdrop/api-client/dist/client.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/chat.d.ts +120 -21
- package/node_modules/@playdrop/api-client/dist/domains/chat.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/chat.js +395 -100
- package/node_modules/@playdrop/api-client/dist/index.d.ts +1 -1
- package/node_modules/@playdrop/api-client/dist/index.d.ts.map +1 -1
- package/node_modules/@playdrop/config/client-meta.json +2 -2
- package/node_modules/@playdrop/types/dist/api.d.ts +2 -2
- package/node_modules/@playdrop/types/dist/api.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/api.js +5 -7
- package/node_modules/@playdrop/types/dist/chat.d.ts +169 -31
- package/node_modules/@playdrop/types/dist/chat.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/chat.js +7 -2
- package/package.json +1 -1
|
@@ -21,175 +21,299 @@ __export(chat_exports, {
|
|
|
21
21
|
});
|
|
22
22
|
module.exports = __toCommonJS(chat_exports);
|
|
23
23
|
var import_request = require("../core/request.js");
|
|
24
|
-
function
|
|
24
|
+
function chatWebSocketUrl(baseUrl) {
|
|
25
|
+
const url = new URL(baseUrl);
|
|
26
|
+
if (url.protocol === "https:")
|
|
27
|
+
url.protocol = "wss:";
|
|
28
|
+
else if (url.protocol === "http:")
|
|
29
|
+
url.protocol = "ws:";
|
|
30
|
+
else
|
|
31
|
+
throw new Error("chat_realtime_invalid_api_url");
|
|
32
|
+
url.pathname = `${url.pathname.replace(/\/$/, "")}/chat/ws`;
|
|
33
|
+
url.search = "";
|
|
34
|
+
url.hash = "";
|
|
35
|
+
return url.toString();
|
|
36
|
+
}
|
|
37
|
+
function parseRealtimeFrame(value) {
|
|
38
|
+
if (typeof value !== "string")
|
|
39
|
+
throw new Error("chat_realtime_invalid_frame");
|
|
40
|
+
let parsed;
|
|
41
|
+
try {
|
|
42
|
+
parsed = JSON.parse(value);
|
|
43
|
+
} catch {
|
|
44
|
+
throw new Error("chat_realtime_invalid_frame");
|
|
45
|
+
}
|
|
46
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
47
|
+
throw new Error("chat_realtime_invalid_frame");
|
|
48
|
+
const frame = parsed;
|
|
49
|
+
const type = frame["type"];
|
|
50
|
+
if (type === "ready" && typeof frame["heartbeatIntervalMs"] === "number")
|
|
51
|
+
return parsed;
|
|
52
|
+
if ((type === "subscribed" || type === "inbox.updated" || type === "resync_required") && typeof frame["conversationId"] === "string") {
|
|
53
|
+
return parsed;
|
|
54
|
+
}
|
|
55
|
+
if (type === "conversation.event" && frame["event"] && typeof frame["event"] === "object") {
|
|
56
|
+
return parsed;
|
|
57
|
+
}
|
|
58
|
+
if (type === "typing.updated" && typeof frame["conversationId"] === "string" && typeof frame["userId"] === "number" && typeof frame["active"] === "boolean" && typeof frame["expiresAt"] === "string") {
|
|
59
|
+
return parsed;
|
|
60
|
+
}
|
|
61
|
+
if (type === "error" && typeof frame["code"] === "string")
|
|
62
|
+
return parsed;
|
|
63
|
+
throw new Error("chat_realtime_invalid_frame");
|
|
64
|
+
}
|
|
65
|
+
function pageQuery(options = {}, legacy = false) {
|
|
25
66
|
const params = new URLSearchParams();
|
|
26
|
-
if (options.beforeId !== void 0)
|
|
27
|
-
params.set("beforeId",
|
|
67
|
+
if (legacy && options.beforeId !== void 0)
|
|
68
|
+
params.set("beforeId", options.beforeId);
|
|
69
|
+
if (!legacy && options.before !== void 0)
|
|
70
|
+
params.set("before", options.before);
|
|
71
|
+
if (!legacy && options.after !== void 0)
|
|
72
|
+
params.set("after", options.after);
|
|
73
|
+
if (!legacy && options.around !== void 0)
|
|
74
|
+
params.set("around", options.around);
|
|
28
75
|
if (options.limit !== void 0)
|
|
29
76
|
params.set("limit", String(options.limit));
|
|
30
77
|
const query = params.toString();
|
|
31
78
|
return query ? `?${query}` : "";
|
|
32
79
|
}
|
|
33
|
-
function
|
|
34
|
-
const
|
|
35
|
-
if (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
...input.body !== void 0 ? { body: input.body } : {},
|
|
46
|
-
...input.attachments !== void 0 ? { attachments: input.attachments } : {},
|
|
47
|
-
..."clientKey" in input && input.clientKey !== void 0 ? { clientKey: input.clientKey } : {},
|
|
48
|
-
...input.eventType !== void 0 ? { eventType: input.eventType } : {},
|
|
49
|
-
...input.eventData !== void 0 ? { eventData: input.eventData } : {},
|
|
50
|
-
..."asSystem" in input && input.asSystem !== void 0 ? { asSystem: input.asSystem } : {}
|
|
51
|
-
};
|
|
80
|
+
function listQuery(input = {}) {
|
|
81
|
+
const params = new URLSearchParams();
|
|
82
|
+
if (input.type)
|
|
83
|
+
params.set("type", input.type);
|
|
84
|
+
if (input.cursor)
|
|
85
|
+
params.set("cursor", input.cursor);
|
|
86
|
+
if (input.limit !== void 0)
|
|
87
|
+
params.set("limit", String(input.limit));
|
|
88
|
+
if (input.query)
|
|
89
|
+
params.set("query", input.query);
|
|
90
|
+
const query = params.toString();
|
|
91
|
+
return query ? `?${query}` : "";
|
|
52
92
|
}
|
|
53
93
|
function buildChatApiClientMethods(input) {
|
|
54
94
|
const { request, handleApiError, fetchImpl, includeBrowserCredentials, resolveBaseUrl, resolveUrl, parseResponseBody, resolveToken, getClientHeaders } = input;
|
|
55
|
-
async function authorizedHeaders() {
|
|
95
|
+
async function authorizedHeaders(contentType) {
|
|
56
96
|
const headers = new Headers(getClientHeaders());
|
|
57
|
-
|
|
97
|
+
if (contentType)
|
|
98
|
+
headers.set("content-type", contentType);
|
|
99
|
+
else
|
|
100
|
+
headers.delete("content-type");
|
|
58
101
|
headers.set("accept", "application/json");
|
|
59
102
|
const token = await resolveToken();
|
|
60
103
|
if (token)
|
|
61
104
|
headers.set("authorization", `Bearer ${token}`);
|
|
62
105
|
return headers;
|
|
63
106
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
for (const link of message.links ?? [])
|
|
68
|
-
form.append("link", link);
|
|
69
|
-
for (const attachment of message.files ?? [])
|
|
70
|
-
form.append("file", attachment.file, fileName(attachment));
|
|
71
|
-
const response = await fetchImpl(resolveUrl(resolveBaseUrl(), path), {
|
|
72
|
-
method,
|
|
73
|
-
headers: await authorizedHeaders(),
|
|
74
|
-
body: form,
|
|
75
|
-
...(0, import_request.buildBrowserCredentialsInit)(includeBrowserCredentials)
|
|
76
|
-
});
|
|
77
|
-
const body = await parseResponseBody(response);
|
|
78
|
-
const result = { status: response.status, body, headers: response.headers };
|
|
79
|
-
if (response.status !== 200 && response.status !== 201)
|
|
80
|
-
handleApiError(result, "chat_write_failed");
|
|
81
|
-
return body;
|
|
82
|
-
}
|
|
83
|
-
return {
|
|
84
|
-
async fetchChatChannels() {
|
|
85
|
-
const response = await request({ method: "GET", path: "/chat/channels" });
|
|
107
|
+
const methods = {
|
|
108
|
+
async fetchChatConversations(options = {}) {
|
|
109
|
+
const response = await request({ method: "GET", path: `/chat/conversations${listQuery(options)}` });
|
|
86
110
|
if (response.status !== 200)
|
|
87
|
-
handleApiError(response, "
|
|
111
|
+
handleApiError(response, "fetch_chat_conversations");
|
|
88
112
|
return response.body;
|
|
89
113
|
},
|
|
90
|
-
async
|
|
114
|
+
async fetchChatConversation(conversationId) {
|
|
115
|
+
const response = await request({ method: "GET", path: `/chat/conversations/${encodeURIComponent(conversationId)}` });
|
|
116
|
+
if (response.status !== 200)
|
|
117
|
+
handleApiError(response, "fetch_chat_conversation");
|
|
118
|
+
return response.body;
|
|
119
|
+
},
|
|
120
|
+
async createDirectChatConversation(username) {
|
|
121
|
+
const response = await request({ method: "POST", path: "/chat/direct-conversations", body: { username } });
|
|
122
|
+
if (response.status !== 200 && response.status !== 201)
|
|
123
|
+
handleApiError(response, "create_direct_chat_conversation");
|
|
124
|
+
return response.body;
|
|
125
|
+
},
|
|
126
|
+
async fetchConversationMessages(conversationId, options = {}) {
|
|
91
127
|
const response = await request({
|
|
92
128
|
method: "GET",
|
|
93
|
-
path: `/chat/
|
|
129
|
+
path: `/chat/conversations/${encodeURIComponent(conversationId)}/messages${pageQuery(options)}`
|
|
94
130
|
});
|
|
95
131
|
if (response.status !== 200)
|
|
96
132
|
handleApiError(response, "fetch_chat_messages");
|
|
97
133
|
return response.body;
|
|
98
134
|
},
|
|
99
|
-
async
|
|
135
|
+
async sendConversationMessage(conversationId, message) {
|
|
100
136
|
const response = await request({
|
|
101
|
-
method: "
|
|
102
|
-
path: `/chat/
|
|
103
|
-
body:
|
|
137
|
+
method: "POST",
|
|
138
|
+
path: `/chat/conversations/${encodeURIComponent(conversationId)}/messages`,
|
|
139
|
+
body: message
|
|
104
140
|
});
|
|
105
|
-
if (response.status !==
|
|
106
|
-
handleApiError(response, "
|
|
141
|
+
if (response.status !== 201)
|
|
142
|
+
handleApiError(response, "send_chat_message");
|
|
107
143
|
return response.body;
|
|
108
144
|
},
|
|
109
|
-
async
|
|
145
|
+
async sendSystemChatMessage(channel, message) {
|
|
110
146
|
const response = await request({
|
|
111
|
-
method: "
|
|
112
|
-
path: `/chat/
|
|
147
|
+
method: "POST",
|
|
148
|
+
path: `/admin/chat/channels/${encodeURIComponent(channel)}/system-messages`,
|
|
149
|
+
body: message
|
|
113
150
|
});
|
|
114
|
-
if (response.status !==
|
|
115
|
-
handleApiError(response, "
|
|
116
|
-
return response.body;
|
|
117
|
-
},
|
|
118
|
-
async sendChatMessage(channel, message) {
|
|
119
|
-
const path = `/chat/channels/${encodeURIComponent(channel)}/messages`;
|
|
120
|
-
if (needsMultipart(message))
|
|
121
|
-
return await multipartWrite("POST", path, message);
|
|
122
|
-
const response = await request({ method: "POST", path, body: jsonPayload(message) });
|
|
123
|
-
if (response.status !== 200 && response.status !== 201)
|
|
124
|
-
handleApiError(response, "send_chat_message");
|
|
151
|
+
if (response.status !== 201)
|
|
152
|
+
handleApiError(response, "send_system_chat_message");
|
|
125
153
|
return response.body;
|
|
126
154
|
},
|
|
127
155
|
async replyChatMessage(messageId, message) {
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
156
|
+
const response = await request({
|
|
157
|
+
method: "POST",
|
|
158
|
+
path: `/chat/messages/${encodeURIComponent(messageId)}/replies`,
|
|
159
|
+
body: message
|
|
160
|
+
});
|
|
161
|
+
if (response.status !== 201)
|
|
133
162
|
handleApiError(response, "reply_chat_message");
|
|
134
163
|
return response.body;
|
|
135
164
|
},
|
|
165
|
+
async replySystemChatMessage(messageId, message) {
|
|
166
|
+
const response = await request({
|
|
167
|
+
method: "POST",
|
|
168
|
+
path: `/admin/chat/messages/${encodeURIComponent(messageId)}/system-replies`,
|
|
169
|
+
body: message
|
|
170
|
+
});
|
|
171
|
+
if (response.status !== 201)
|
|
172
|
+
handleApiError(response, "reply_system_chat_message");
|
|
173
|
+
return response.body;
|
|
174
|
+
},
|
|
136
175
|
async editChatMessage(messageId, message) {
|
|
137
|
-
const
|
|
138
|
-
if (needsMultipart(message))
|
|
139
|
-
return await multipartWrite("PATCH", path, message);
|
|
140
|
-
const response = await request({ method: "PATCH", path, body: jsonPayload(message) });
|
|
176
|
+
const response = await request({ method: "PATCH", path: `/chat/messages/${encodeURIComponent(messageId)}`, body: message });
|
|
141
177
|
if (response.status !== 200)
|
|
142
178
|
handleApiError(response, "edit_chat_message");
|
|
143
179
|
return response.body;
|
|
144
180
|
},
|
|
181
|
+
async deleteChatMessage(messageId) {
|
|
182
|
+
const response = await request({ method: "DELETE", path: `/chat/messages/${encodeURIComponent(messageId)}` });
|
|
183
|
+
if (response.status !== 200)
|
|
184
|
+
handleApiError(response, "delete_chat_message");
|
|
185
|
+
return response.body;
|
|
186
|
+
},
|
|
187
|
+
async fetchChatThread(messageId, options = {}) {
|
|
188
|
+
const response = await request({ method: "GET", path: `/chat/messages/${encodeURIComponent(messageId)}/thread${pageQuery(options)}` });
|
|
189
|
+
if (response.status !== 200)
|
|
190
|
+
handleApiError(response, "fetch_chat_thread");
|
|
191
|
+
return response.body;
|
|
192
|
+
},
|
|
145
193
|
async reactChatMessage(messageId, emoji) {
|
|
146
|
-
const response = await request({
|
|
147
|
-
method: "PUT",
|
|
148
|
-
path: `/chat/messages/${encodeURIComponent(String(messageId))}/reactions/${encodeURIComponent(emoji)}`
|
|
149
|
-
});
|
|
194
|
+
const response = await request({ method: "PUT", path: `/chat/messages/${encodeURIComponent(messageId)}/reactions/${encodeURIComponent(emoji)}` });
|
|
150
195
|
if (response.status !== 200)
|
|
151
196
|
handleApiError(response, "react_chat_message");
|
|
152
197
|
return response.body;
|
|
153
198
|
},
|
|
154
199
|
async unreactChatMessage(messageId, emoji) {
|
|
155
|
-
const response = await request({
|
|
156
|
-
method: "DELETE",
|
|
157
|
-
path: `/chat/messages/${encodeURIComponent(String(messageId))}/reactions/${encodeURIComponent(emoji)}`
|
|
158
|
-
});
|
|
200
|
+
const response = await request({ method: "DELETE", path: `/chat/messages/${encodeURIComponent(messageId)}/reactions/${encodeURIComponent(emoji)}` });
|
|
159
201
|
if (response.status !== 200)
|
|
160
202
|
handleApiError(response, "unreact_chat_message");
|
|
161
203
|
return response.body;
|
|
162
204
|
},
|
|
163
|
-
async
|
|
205
|
+
async markChatConversationRead(conversationId, lastReadMessageId) {
|
|
164
206
|
const response = await request({
|
|
165
207
|
method: "PUT",
|
|
166
|
-
path: `/
|
|
167
|
-
body: {
|
|
208
|
+
path: `/chat/conversations/${encodeURIComponent(conversationId)}/read`,
|
|
209
|
+
body: { lastReadMessageId }
|
|
168
210
|
});
|
|
169
211
|
if (response.status !== 200)
|
|
170
|
-
handleApiError(response, "
|
|
212
|
+
handleApiError(response, "mark_chat_conversation_read");
|
|
171
213
|
return response.body;
|
|
172
214
|
},
|
|
173
|
-
async
|
|
215
|
+
async updateChatConversationState(conversationId, state) {
|
|
174
216
|
const response = await request({
|
|
175
|
-
method: "
|
|
176
|
-
path: `/
|
|
217
|
+
method: "PATCH",
|
|
218
|
+
path: `/chat/conversations/${encodeURIComponent(conversationId)}/state`,
|
|
219
|
+
body: state
|
|
177
220
|
});
|
|
221
|
+
if (response.status !== 200)
|
|
222
|
+
handleApiError(response, "update_chat_conversation_state");
|
|
223
|
+
return response.body;
|
|
224
|
+
},
|
|
225
|
+
async reportChatMessage(messageId, body) {
|
|
226
|
+
const response = await request({ method: "POST", path: `/chat/messages/${encodeURIComponent(messageId)}/report`, body });
|
|
227
|
+
if (response.status !== 201)
|
|
228
|
+
handleApiError(response, "report_chat_message");
|
|
229
|
+
return response.body;
|
|
230
|
+
},
|
|
231
|
+
async fetchChatFriends(options = {}) {
|
|
232
|
+
const response = await request({ method: "GET", path: `/me/friends${listQuery(options)}` });
|
|
233
|
+
if (response.status !== 200)
|
|
234
|
+
handleApiError(response, "fetch_chat_friends");
|
|
235
|
+
return response.body;
|
|
236
|
+
},
|
|
237
|
+
async fetchChatNotificationPreferences() {
|
|
238
|
+
const response = await request({ method: "GET", path: "/me/chat-notification-preferences" });
|
|
239
|
+
if (response.status !== 200)
|
|
240
|
+
handleApiError(response, "fetch_chat_notification_preferences");
|
|
241
|
+
return response.body;
|
|
242
|
+
},
|
|
243
|
+
async updateChatNotificationPreferences(preferences) {
|
|
244
|
+
const response = await request({ method: "PATCH", path: "/me/chat-notification-preferences", body: preferences });
|
|
245
|
+
if (response.status !== 200)
|
|
246
|
+
handleApiError(response, "update_chat_notification_preferences");
|
|
247
|
+
return response.body;
|
|
248
|
+
},
|
|
249
|
+
async createChatAttachmentUploadSession(conversationId, file) {
|
|
250
|
+
const response = await request({
|
|
251
|
+
method: "POST",
|
|
252
|
+
path: `/chat/conversations/${encodeURIComponent(conversationId)}/attachment-upload-sessions`,
|
|
253
|
+
body: file
|
|
254
|
+
});
|
|
255
|
+
if (response.status !== 201)
|
|
256
|
+
handleApiError(response, "create_chat_attachment_upload_session");
|
|
257
|
+
return response.body;
|
|
258
|
+
},
|
|
259
|
+
async uploadChatAttachment(session, file) {
|
|
260
|
+
const isSignedUpload = /^https?:/i.test(session.uploadUrl);
|
|
261
|
+
const response = await fetchImpl(resolveUrl(resolveBaseUrl(), session.uploadUrl), {
|
|
262
|
+
method: session.uploadMethod,
|
|
263
|
+
headers: isSignedUpload ? { "content-type": file.type || "application/octet-stream", ...session.uploadHeaders } : await authorizedHeaders(file.type || "application/octet-stream"),
|
|
264
|
+
body: file,
|
|
265
|
+
...!isSignedUpload ? (0, import_request.buildBrowserCredentialsInit)(includeBrowserCredentials) : {}
|
|
266
|
+
});
|
|
267
|
+
if (!response.ok) {
|
|
268
|
+
const body = await parseResponseBody(response);
|
|
269
|
+
handleApiError({ status: response.status, body, headers: response.headers }, "upload_chat_attachment");
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
async completeChatAttachmentUploadSession(sessionId) {
|
|
273
|
+
const response = await request({ method: "POST", path: `/chat/attachment-upload-sessions/${encodeURIComponent(sessionId)}/complete` });
|
|
274
|
+
if (response.status !== 200)
|
|
275
|
+
handleApiError(response, "complete_chat_attachment_upload_session");
|
|
276
|
+
},
|
|
277
|
+
async abortChatAttachmentUploadSession(sessionId) {
|
|
278
|
+
const response = await request({ method: "DELETE", path: `/chat/attachment-upload-sessions/${encodeURIComponent(sessionId)}` });
|
|
178
279
|
if (response.status !== 204)
|
|
179
|
-
handleApiError(response, "
|
|
280
|
+
handleApiError(response, "abort_chat_attachment_upload_session");
|
|
281
|
+
},
|
|
282
|
+
async createCommunityChatChannel(input2) {
|
|
283
|
+
const response = await request({ method: "POST", path: "/admin/chat/community-channels", body: input2 });
|
|
284
|
+
if (response.status !== 201)
|
|
285
|
+
handleApiError(response, "create_community_chat_channel");
|
|
286
|
+
return response.body;
|
|
287
|
+
},
|
|
288
|
+
async updateCommunityChatChannel(conversationId, input2) {
|
|
289
|
+
const response = await request({ method: "PATCH", path: `/admin/chat/community-channels/${encodeURIComponent(conversationId)}`, body: input2 });
|
|
290
|
+
if (response.status !== 200)
|
|
291
|
+
handleApiError(response, "update_community_chat_channel");
|
|
292
|
+
return response.body;
|
|
180
293
|
},
|
|
181
|
-
async
|
|
294
|
+
async fetchAdminDirectConversations(options = {}) {
|
|
295
|
+
const response = await request({ method: "GET", path: `/admin/chat/direct-conversations${listQuery(options)}` });
|
|
296
|
+
if (response.status !== 200)
|
|
297
|
+
handleApiError(response, "fetch_admin_direct_conversations");
|
|
298
|
+
return response.body;
|
|
299
|
+
},
|
|
300
|
+
async fetchAdminDirectConversationMessages(conversationId, options = {}) {
|
|
301
|
+
const response = await request({ method: "GET", path: `/admin/chat/direct-conversations/${encodeURIComponent(conversationId)}/messages${pageQuery(options)}` });
|
|
302
|
+
if (response.status !== 200)
|
|
303
|
+
handleApiError(response, "fetch_admin_direct_conversation_messages");
|
|
304
|
+
return response.body;
|
|
305
|
+
},
|
|
306
|
+
async moderateAdminDirectConversationMessage(conversationId, messageId) {
|
|
182
307
|
const response = await request({
|
|
183
|
-
method: "
|
|
184
|
-
path: `/admin/chat/
|
|
185
|
-
body: { readPolicy }
|
|
308
|
+
method: "DELETE",
|
|
309
|
+
path: `/admin/chat/direct-conversations/${encodeURIComponent(conversationId)}/messages/${encodeURIComponent(messageId)}`
|
|
186
310
|
});
|
|
187
311
|
if (response.status !== 200)
|
|
188
|
-
handleApiError(response, "
|
|
312
|
+
handleApiError(response, "moderate_admin_direct_conversation_message");
|
|
189
313
|
return response.body;
|
|
190
314
|
},
|
|
191
315
|
async fetchChatAttachment(attachmentId) {
|
|
192
|
-
const response = await fetchImpl(resolveUrl(resolveBaseUrl(), `/chat/attachments/${encodeURIComponent(
|
|
316
|
+
const response = await fetchImpl(resolveUrl(resolveBaseUrl(), `/chat/attachments/${encodeURIComponent(attachmentId)}`), {
|
|
193
317
|
method: "GET",
|
|
194
318
|
headers: await authorizedHeaders(),
|
|
195
319
|
...(0, import_request.buildBrowserCredentialsInit)(includeBrowserCredentials)
|
|
@@ -199,8 +323,179 @@ function buildChatApiClientMethods(input) {
|
|
|
199
323
|
handleApiError({ status: response.status, body, headers: response.headers }, "fetch_chat_attachment");
|
|
200
324
|
}
|
|
201
325
|
return await response.blob();
|
|
326
|
+
},
|
|
327
|
+
async fetchChatChannels() {
|
|
328
|
+
const response = await request({ method: "GET", path: "/chat/channels" });
|
|
329
|
+
if (response.status !== 200)
|
|
330
|
+
handleApiError(response, "fetch_chat_channels");
|
|
331
|
+
return response.body;
|
|
332
|
+
},
|
|
333
|
+
async fetchChatMessages(channel, options = {}) {
|
|
334
|
+
const response = await request({ method: "GET", path: `/chat/channels/${encodeURIComponent(channel)}/messages${pageQuery(options, true)}` });
|
|
335
|
+
if (response.status !== 200)
|
|
336
|
+
handleApiError(response, "fetch_chat_messages");
|
|
337
|
+
return response.body;
|
|
338
|
+
},
|
|
339
|
+
async markChatChannelRead(channel, lastReadMessageId) {
|
|
340
|
+
const response = await request({ method: "PUT", path: `/chat/channels/${encodeURIComponent(channel)}/read`, body: { lastReadMessageId } });
|
|
341
|
+
if (response.status !== 200)
|
|
342
|
+
handleApiError(response, "mark_chat_channel_read");
|
|
343
|
+
return response.body;
|
|
344
|
+
},
|
|
345
|
+
async sendChatMessage(channel, message) {
|
|
346
|
+
const response = await request({ method: "POST", path: `/chat/channels/${encodeURIComponent(channel)}/messages`, body: message });
|
|
347
|
+
if (response.status !== 201)
|
|
348
|
+
handleApiError(response, "send_chat_message");
|
|
349
|
+
return response.body;
|
|
350
|
+
},
|
|
351
|
+
connectChatRealtime(options) {
|
|
352
|
+
let socket = null;
|
|
353
|
+
let reconnectTimer = null;
|
|
354
|
+
let stopped = false;
|
|
355
|
+
let attempt = 0;
|
|
356
|
+
const subscriptions = new Map((options.subscriptions ?? []).map((subscription) => [
|
|
357
|
+
subscription.conversationId,
|
|
358
|
+
subscription.lastEventVersion ?? null
|
|
359
|
+
]));
|
|
360
|
+
const notifyState = (state) => options.onStateChange?.(state);
|
|
361
|
+
const factory = options.webSocketFactory ?? ((url) => {
|
|
362
|
+
if (typeof globalThis.WebSocket !== "function")
|
|
363
|
+
throw new Error("chat_realtime_websocket_unavailable");
|
|
364
|
+
return new globalThis.WebSocket(url);
|
|
365
|
+
});
|
|
366
|
+
const send = (frame) => {
|
|
367
|
+
if (socket?.readyState === 1)
|
|
368
|
+
socket.send(JSON.stringify(frame));
|
|
369
|
+
};
|
|
370
|
+
const sendSubscriptions = () => {
|
|
371
|
+
for (const [conversationId, lastEventVersion] of subscriptions) {
|
|
372
|
+
send({ type: "subscribe", conversationId, lastEventVersion });
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
const scheduleReconnect = () => {
|
|
376
|
+
if (stopped || reconnectTimer)
|
|
377
|
+
return;
|
|
378
|
+
notifyState("reconnecting");
|
|
379
|
+
const exponentialDelay = Math.min(500 * 2 ** Math.min(attempt, 6), 3e4);
|
|
380
|
+
const delay = Math.round(exponentialDelay * (0.8 + Math.random() * 0.4));
|
|
381
|
+
attempt += 1;
|
|
382
|
+
reconnectTimer = setTimeout(() => {
|
|
383
|
+
reconnectTimer = null;
|
|
384
|
+
void connect();
|
|
385
|
+
}, delay);
|
|
386
|
+
};
|
|
387
|
+
const connect = async () => {
|
|
388
|
+
if (stopped)
|
|
389
|
+
return;
|
|
390
|
+
notifyState(attempt === 0 ? "connecting" : "reconnecting");
|
|
391
|
+
let token;
|
|
392
|
+
try {
|
|
393
|
+
token = await resolveToken();
|
|
394
|
+
if (!token)
|
|
395
|
+
throw new Error("chat_realtime_unauthorized");
|
|
396
|
+
socket = factory(chatWebSocketUrl(resolveBaseUrl()));
|
|
397
|
+
} catch (error) {
|
|
398
|
+
const code = error instanceof Error ? error.message : "chat_realtime_connection_failed";
|
|
399
|
+
options.onError?.(code);
|
|
400
|
+
if (code === "chat_realtime_unauthorized") {
|
|
401
|
+
stopped = true;
|
|
402
|
+
notifyState("closed");
|
|
403
|
+
} else
|
|
404
|
+
scheduleReconnect();
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
const activeSocket = socket;
|
|
408
|
+
activeSocket.addEventListener("open", () => {
|
|
409
|
+
if (!stopped && activeSocket === socket)
|
|
410
|
+
activeSocket.send(JSON.stringify({ type: "auth", token }));
|
|
411
|
+
});
|
|
412
|
+
activeSocket.addEventListener("message", (event) => {
|
|
413
|
+
if (stopped || activeSocket !== socket)
|
|
414
|
+
return;
|
|
415
|
+
try {
|
|
416
|
+
const frame = parseRealtimeFrame(event.data);
|
|
417
|
+
if (frame.type === "ready") {
|
|
418
|
+
attempt = 0;
|
|
419
|
+
notifyState("ready");
|
|
420
|
+
sendSubscriptions();
|
|
421
|
+
} else if (frame.type === "subscribed") {
|
|
422
|
+
subscriptions.set(frame.conversationId, frame.eventVersion);
|
|
423
|
+
} else if (frame.type === "conversation.event") {
|
|
424
|
+
try {
|
|
425
|
+
options.onEvent(frame.event);
|
|
426
|
+
subscriptions.set(frame.event.conversationId, frame.event.version);
|
|
427
|
+
} catch {
|
|
428
|
+
options.onError?.("chat_realtime_event_handler_failed");
|
|
429
|
+
activeSocket.close(1011, "chat_realtime_event_handler_failed");
|
|
430
|
+
}
|
|
431
|
+
} else if (frame.type === "inbox.updated") {
|
|
432
|
+
options.onInboxUpdated?.(frame.conversationId);
|
|
433
|
+
} else if (frame.type === "typing.updated") {
|
|
434
|
+
options.onTypingUpdated?.(frame);
|
|
435
|
+
} else if (frame.type === "resync_required") {
|
|
436
|
+
subscriptions.set(frame.conversationId, null);
|
|
437
|
+
options.onResyncRequired?.(frame.conversationId);
|
|
438
|
+
} else {
|
|
439
|
+
options.onError?.(frame.code);
|
|
440
|
+
if (frame.code === "chat_realtime_unauthorized")
|
|
441
|
+
stopped = true;
|
|
442
|
+
}
|
|
443
|
+
} catch (error) {
|
|
444
|
+
options.onError?.(error instanceof Error ? error.message : "chat_realtime_invalid_frame");
|
|
445
|
+
activeSocket.close(1008, "chat_realtime_invalid_frame");
|
|
446
|
+
}
|
|
447
|
+
});
|
|
448
|
+
activeSocket.addEventListener("error", () => {
|
|
449
|
+
if (!stopped && activeSocket === socket)
|
|
450
|
+
options.onError?.("chat_realtime_connection_failed");
|
|
451
|
+
});
|
|
452
|
+
activeSocket.addEventListener("close", (event) => {
|
|
453
|
+
if (activeSocket !== socket)
|
|
454
|
+
return;
|
|
455
|
+
socket = null;
|
|
456
|
+
if (stopped)
|
|
457
|
+
notifyState("closed");
|
|
458
|
+
else if (event.code === 1008) {
|
|
459
|
+
stopped = true;
|
|
460
|
+
options.onError?.(event.reason || "chat_realtime_forbidden");
|
|
461
|
+
notifyState("closed");
|
|
462
|
+
} else
|
|
463
|
+
scheduleReconnect();
|
|
464
|
+
});
|
|
465
|
+
};
|
|
466
|
+
void connect();
|
|
467
|
+
return {
|
|
468
|
+
close() {
|
|
469
|
+
if (stopped)
|
|
470
|
+
return;
|
|
471
|
+
stopped = true;
|
|
472
|
+
if (reconnectTimer)
|
|
473
|
+
clearTimeout(reconnectTimer);
|
|
474
|
+
reconnectTimer = null;
|
|
475
|
+
socket?.close(1e3, "chat_realtime_client_closed");
|
|
476
|
+
socket = null;
|
|
477
|
+
notifyState("closed");
|
|
478
|
+
},
|
|
479
|
+
subscribe(conversationId, lastEventVersion = null) {
|
|
480
|
+
subscriptions.set(conversationId, lastEventVersion);
|
|
481
|
+
send({ type: "subscribe", conversationId, lastEventVersion });
|
|
482
|
+
},
|
|
483
|
+
unsubscribe(conversationId) {
|
|
484
|
+
subscriptions.delete(conversationId);
|
|
485
|
+
send({ type: "unsubscribe", conversationId });
|
|
486
|
+
},
|
|
487
|
+
setTyping(conversationId, active) {
|
|
488
|
+
if (!subscriptions.has(conversationId))
|
|
489
|
+
throw new Error("chat_realtime_not_subscribed");
|
|
490
|
+
send({ type: "typing", conversationId, active });
|
|
491
|
+
},
|
|
492
|
+
getLastEventVersion(conversationId) {
|
|
493
|
+
return subscriptions.get(conversationId) ?? null;
|
|
494
|
+
}
|
|
495
|
+
};
|
|
202
496
|
}
|
|
203
497
|
};
|
|
498
|
+
return methods;
|
|
204
499
|
}
|
|
205
500
|
// Annotate the CommonJS export names for ESM import in node:
|
|
206
501
|
0 && (module.exports = {
|
|
@@ -3,7 +3,7 @@ export type { ApiClient, ApiClientConfig, ApiRequest, ApiResponse, GameplaySessi
|
|
|
3
3
|
import type { FinalizeAppUploadRequest, InitializeAppUploadRequest, RecordAppUploadLaunchCheckRequest, TweakValues } from "@playdrop/types";
|
|
4
4
|
import type { UploadAppSessionFileOptions } from "./client.js";
|
|
5
5
|
export type { AdminAgentTaskTranscriptOptions, CreationGamesFetchResult, GetCreationConversationOptions, ListAgentTasksOptions, ListCreatorGamesOptions, UploadWorkerAgentTaskMaterialOptions, } from "./domains/agent-tasks.js";
|
|
6
|
-
export type { ChatEditOptions, ChatFileInput, ChatPageOptions, ChatWriteOptions } from "./domains/chat.js";
|
|
6
|
+
export type { ChatEditOptions, ChatFileInput, ChatPageOptions, ChatRealtimeConnection, ChatRealtimeConnectionOptions, ChatRealtimeConnectionState, ChatRealtimeSocket, ChatSystemWriteOptions, ChatWriteOptions, } from "./domains/chat.js";
|
|
7
7
|
import type { AcquisitionAttributionRequest, AdminCreatorEngagementRulePreviewRequest, AdminGameCollectionCandidatesResponse, AdminGameCollectionResponse, AdminGameCollectionsResponse, AdminMutateAchievementStateRequest, AdminMutateLeaderboardScoreRequest, AgentTaskAttachmentUploadResponse, AgentTaskCreatorFeedbackStatus, AgentTaskKind, AgentTaskNewGameSuggestionsResponse, ApiKeyLoginRequest, AppBrowseRequest, AppListingDraftMediaSlot, AppAuthMode, AppDetailRequest, AppDetailResponse, AppleLinkRequest, AppleNativeChallengeResponse, AppleOAuthHandoffExchangeRequest, AppleOAuthLinkStartRequest, ApplePendingSignupResponse, ApplePushDeviceRequest, AppleSignInRequest, AppLogEntryRequest, AppMoreCollectionKey, AppMoreCollectionPage, AppMoreCollectionRequest, AppMoreCollectionsRequest, AppMoreCollectionsResponse, AppResponse, AppSurface, AppType, AppVersionVisibility, AssetBrowseKind, AssetCategory, AssetListSort, AssetPackListSort, AssetPackResponse, AssetResponse, AssetSpecResponse, AssetSummaryResponse, BoostPurchaseRequest, BoostReportQuery, ClaimFreeCreditRewardResponse, ClearAgentTaskResponse, CliLoginApproveRequest, CliLoginPollRequest, CliWebLaunchStartRequest, CompleteAppleSignupRequest, CompleteGoogleSignupRequest, CompleteXSignupRequest, ContentLicense, CreateAdminGameCollectionRequest, CreateAppAgentTaskRequest, CreateCommentReportRequest, CreateCliApiTokenRequest, CreateContentCommentRequest, CompletePlayTradeSessionRequest, CreatePlayTradeSessionRequest, PlayTradeActivityRequest, CreateContentReportRequest, CreateCreatorReportRequest, CreateNewGameAgentTaskRequest, CreateStaticGameAgentTaskRequest, CreateRemixGameAgentTaskRequest, CreditPackCheckoutSessionRequest, CreatorPlanSessionRequest, CreatorAppsBrowseRequest, CreatorBlockMutationResponse, CreatorEngagementRuleExecutionStatus, CreatorFollowMutationResponse, DeleteMyAccountRequest, DislikedItemMutationResponse, FeedbackCategory, FeedbackClient, FeedbackStatus, FetchHomeOptions, FirebasePushDeviceRequest, FollowingFeedSection, FollowingSort, FreeCreditsResponse, GoogleAppleLinkRequest, GoogleAppleSignInRequest, GoogleOneTapExchangeRequest, GameplaySessionStartRequest, GameplaySessionActivityRequest, IapPurchaseRequest, IapReceiptListParams, InvitePreviewResponse, LibraryCategory, LibrarySort, LikedItemMutationResponse, ModerationReportResponse, NativeOAuthHandoffExchangeRequest, NativeOAuthLinkStartRequest, MyInviteCodeResponse, NotificationStatus, PublicEmailPreferencesUpdateRequest, ResolveRuntimeAssetsRequest, RetryAgentTaskResponse, RegisterAgentBundleRequest, ReviewState, SavedItemKind, SearchRequest, SearchSuggestRequest, SupportedLocale, SubmitCreatorSurveyRequest, SubmitCreatorSurveyResponse, SubmitFeedbackRequest, TrackEngagementEventRequest, TrackEngagementEventResponse, UpdateAdminFeedbackRequest, UpdateAdminGameCollectionGamesRequest, UpdateAdminGameCollectionRequest, UpdateAssetPackRequest, UpdateAssetPackVersionRequest, UpdateAssetRequest, UpdateAssetVersionRequest, UpdateProfileRequest, UpdatePreferredLocaleRequest, UpdateUserCommunicationPreferencesRequest, UpsertWebPushSubscriptionRequest, WorkerAgentTaskAttemptUnavailableRequest, WorkerAcknowledgeAgentTaskClaimRequest, WorkerClaimAgentTaskRequest, WorkerClaimAgentTaskSlugRequest, WorkerCompleteAgentTaskRequest, WorkerCompleteReleaseSmokeRequest, WorkerCreateAgentTaskEventRequest, WorkerCreateAgentTaskTranscriptChunkRequest, WorkerFailAgentTaskRequest, WorkerHeartbeatAgentTaskRequest, WorkerPresenceRequest, WorkerRecordAgentTaskRunTelemetryRequest, WorkerSubmitAgentTaskReviewRequest, WorkerUpdateIntentRequest } from "@playdrop/types";
|
|
8
8
|
import type { ApiClient } from "./client.js";
|
|
9
9
|
import type { AdminAgentTaskTranscriptOptions, GetCreationConversationOptions, ListAgentTasksOptions, ListCreatorGamesOptions } from "./domains/agent-tasks.js";
|