replicas-engine 0.1.625 → 0.1.627
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/dist/src/index.js
CHANGED
|
@@ -2101,6 +2101,7 @@ Use this when:
|
|
|
2101
2101
|
- The user asks for ClickHouse analytics or PostHog product data
|
|
2102
2102
|
- The user asks to invoke a connected Modal function
|
|
2103
2103
|
- The user asks to query or update a connected turbopuffer namespace
|
|
2104
|
+
- The user asks for PlanetScale organizations, databases, branches, or Insights data
|
|
2104
2105
|
- The user asks to analyze text with Pangram
|
|
2105
2106
|
- The user asks for Stripe customers, payments, invoices, subscriptions, or balances`;
|
|
2106
2107
|
var REFERENCE9 = `# Plugins
|
|
@@ -2156,6 +2157,17 @@ const results = await Promise.all(customerIds.map((customer) =>
|
|
|
2156
2157
|
|
|
2157
2158
|
Never attempt to import Composio, create a session, manage a connection, or call a provider with raw credentials. Those operations are intentionally unavailable inside the workspace.
|
|
2158
2159
|
|
|
2160
|
+
## PlanetScale
|
|
2161
|
+
|
|
2162
|
+
PlanetScale is a native OAuth integration. Pass a relative path from the PlanetScale v1 API; Replicas refreshes access tokens server-side:
|
|
2163
|
+
|
|
2164
|
+
\`\`\`ts
|
|
2165
|
+
const organizations = await replicas.planetscale.request('/organizations');
|
|
2166
|
+
const databases = await replicas.planetscale.request('/organizations/acme/databases');
|
|
2167
|
+
\`\`\`
|
|
2168
|
+
|
|
2169
|
+
OAuth scopes control permitted operations. Confirm mutations before using POST, PUT, PATCH, or DELETE.
|
|
2170
|
+
|
|
2159
2171
|
## Modal
|
|
2160
2172
|
|
|
2161
2173
|
Modal is a native integration and uses its official JavaScript SDK behind the Replicas gateway. Invoke a deployed function by name:
|
|
@@ -5363,6 +5375,63 @@ var MEDIA_KIND = {
|
|
|
5363
5375
|
var MEDIA_KINDS = [MEDIA_KIND.IMAGE, MEDIA_KIND.VIDEO, MEDIA_KIND.AUDIO, MEDIA_KIND.HTML];
|
|
5364
5376
|
var PUBLIC_MEDIA_KINDS = [MEDIA_KIND.IMAGE, MEDIA_KIND.VIDEO, MEDIA_KIND.AUDIO];
|
|
5365
5377
|
var MAX_ENGINE_LOG_BYTES = 50 * 1024 * 1024;
|
|
5378
|
+
function normalizeChatMessageSenders(value) {
|
|
5379
|
+
if (!Array.isArray(value)) return void 0;
|
|
5380
|
+
const senders = value.flatMap((sender) => {
|
|
5381
|
+
if (!isChatMessageSender(sender)) return [];
|
|
5382
|
+
const { senderUserId, senderEmail, senderDisplayName, senderAvatarUrl, recordedAt } = sender;
|
|
5383
|
+
return [{
|
|
5384
|
+
senderUserId,
|
|
5385
|
+
senderEmail,
|
|
5386
|
+
...typeof senderDisplayName === "string" ? { senderDisplayName } : {},
|
|
5387
|
+
...typeof senderAvatarUrl === "string" ? { senderAvatarUrl } : {},
|
|
5388
|
+
recordedAt
|
|
5389
|
+
}];
|
|
5390
|
+
});
|
|
5391
|
+
return senders;
|
|
5392
|
+
}
|
|
5393
|
+
function normalizeChatTranscriptMetadata(value) {
|
|
5394
|
+
if (!isRecord(value)) return {};
|
|
5395
|
+
const metadata = {};
|
|
5396
|
+
const {
|
|
5397
|
+
provider,
|
|
5398
|
+
title,
|
|
5399
|
+
createdAt,
|
|
5400
|
+
updatedAt,
|
|
5401
|
+
parentChatId,
|
|
5402
|
+
deletedAt,
|
|
5403
|
+
senders,
|
|
5404
|
+
captureId,
|
|
5405
|
+
captureReason,
|
|
5406
|
+
sha256
|
|
5407
|
+
} = value;
|
|
5408
|
+
if (typeof provider === "string" && isValidAgentProvider(provider)) metadata.provider = provider;
|
|
5409
|
+
if (typeof title === "string") metadata.title = title;
|
|
5410
|
+
if (typeof createdAt === "string") metadata.createdAt = createdAt;
|
|
5411
|
+
if (typeof updatedAt === "string") metadata.updatedAt = updatedAt;
|
|
5412
|
+
if (typeof parentChatId === "string" || parentChatId === null) metadata.parentChatId = parentChatId;
|
|
5413
|
+
if (typeof deletedAt === "string" || deletedAt === null) metadata.deletedAt = deletedAt;
|
|
5414
|
+
const normalizedSenders = normalizeChatMessageSenders(senders);
|
|
5415
|
+
if (normalizedSenders) metadata.senders = normalizedSenders;
|
|
5416
|
+
if (typeof captureId === "string") metadata.captureId = captureId;
|
|
5417
|
+
if (captureReason === "workspace_sleep") metadata.captureReason = captureReason;
|
|
5418
|
+
if (typeof sha256 === "string") metadata.sha256 = sha256;
|
|
5419
|
+
return metadata;
|
|
5420
|
+
}
|
|
5421
|
+
function parseChatTranscriptArtifact(value) {
|
|
5422
|
+
if (!isRecord(value) || typeof value.id !== "string" || typeof value.workspace_id !== "string" || value.kind !== "chat_transcript" || value.provider !== "s3" || typeof value.bucket !== "string" || typeof value.key !== "string" || typeof value.size !== "number" || typeof value.created_at !== "string") return null;
|
|
5423
|
+
return {
|
|
5424
|
+
id: value.id,
|
|
5425
|
+
workspace_id: value.workspace_id,
|
|
5426
|
+
kind: "chat_transcript",
|
|
5427
|
+
provider: "s3",
|
|
5428
|
+
bucket: value.bucket,
|
|
5429
|
+
key: value.key,
|
|
5430
|
+
size: value.size,
|
|
5431
|
+
metadata: normalizeChatTranscriptMetadata(value.metadata),
|
|
5432
|
+
created_at: value.created_at
|
|
5433
|
+
};
|
|
5434
|
+
}
|
|
5366
5435
|
|
|
5367
5436
|
// ../shared/src/memory.ts
|
|
5368
5437
|
var MEMORY_ROOT = `${SANDBOX_PATHS.REPLICAS_DIR}/memories`;
|
|
@@ -10960,7 +11029,7 @@ var DEFAULT_CODEX_ARGS = [
|
|
|
10960
11029
|
var MIN_CODEX_CLI_VERSION = "0.144.6";
|
|
10961
11030
|
var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
|
|
10962
11031
|
var codexCliVersionEnsured = null;
|
|
10963
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
11032
|
+
var ENGINE_PACKAGE_VERSION = "0.1.627";
|
|
10964
11033
|
var INITIALIZE_METHOD = "initialize";
|
|
10965
11034
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
10966
11035
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -15920,6 +15989,7 @@ async function reconcileCanvasItems(filenames) {
|
|
|
15920
15989
|
|
|
15921
15990
|
// src/services/upload-chat-transcripts.ts
|
|
15922
15991
|
import { createReadStream } from "fs";
|
|
15992
|
+
import { createHash as createHash2 } from "crypto";
|
|
15923
15993
|
import { readdir as readdir8, readFile as readFile14, stat as stat4 } from "fs/promises";
|
|
15924
15994
|
import { request as httpRequest } from "http";
|
|
15925
15995
|
import { request as httpsRequest } from "https";
|
|
@@ -15977,9 +16047,10 @@ async function putTranscript(uploadUrl, filePath, size) {
|
|
|
15977
16047
|
file.pipe(request);
|
|
15978
16048
|
});
|
|
15979
16049
|
}
|
|
15980
|
-
async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
|
|
16050
|
+
async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map(), capture) {
|
|
15981
16051
|
let flushed = 0;
|
|
15982
16052
|
let failed = 0;
|
|
16053
|
+
const revisions = [];
|
|
15983
16054
|
const tasks = [];
|
|
15984
16055
|
for (const dir of HISTORY_DIRS) {
|
|
15985
16056
|
let entries;
|
|
@@ -15992,8 +16063,9 @@ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
|
|
|
15992
16063
|
if (!entry.endsWith(".jsonl")) continue;
|
|
15993
16064
|
const chatId = basename2(entry, ".jsonl");
|
|
15994
16065
|
tasks.push(
|
|
15995
|
-
uploadChatTranscript(chatId, join25(dir, entry), chatsById.get(chatId)).then(() => {
|
|
16066
|
+
uploadChatTranscript(chatId, join25(dir, entry), chatsById.get(chatId), capture).then((artifact) => {
|
|
15996
16067
|
flushed++;
|
|
16068
|
+
if (artifact && capture) revisions.push(artifact);
|
|
15997
16069
|
}).catch((err) => {
|
|
15998
16070
|
failed++;
|
|
15999
16071
|
console.error("[ChatTranscriptUploader] upload failed:", { chatId, err });
|
|
@@ -16002,11 +16074,11 @@ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
|
|
|
16002
16074
|
}
|
|
16003
16075
|
}
|
|
16004
16076
|
await Promise.all(tasks);
|
|
16005
|
-
return { flushed, failed };
|
|
16077
|
+
return capture ? { flushed, failed, captureSupported: true, revisions } : { flushed, failed };
|
|
16006
16078
|
}
|
|
16007
|
-
async function uploadChatTranscript(chatId, filePath, chat) {
|
|
16079
|
+
async function uploadChatTranscript(chatId, filePath, chat, capture) {
|
|
16008
16080
|
const { size } = await stat4(filePath);
|
|
16009
|
-
if (size === 0) return;
|
|
16081
|
+
if (size === 0) return null;
|
|
16010
16082
|
const metadata = chat ? {
|
|
16011
16083
|
provider: chat.provider,
|
|
16012
16084
|
title: chat.title,
|
|
@@ -16015,6 +16087,13 @@ async function uploadChatTranscript(chatId, filePath, chat) {
|
|
|
16015
16087
|
parentChatId: chat.parentChatId,
|
|
16016
16088
|
deletedAt: chat.deletedAt ?? null
|
|
16017
16089
|
} : {};
|
|
16090
|
+
if (capture) {
|
|
16091
|
+
const hash = createHash2("sha256");
|
|
16092
|
+
for await (const chunk of createReadStream(filePath)) hash.update(chunk);
|
|
16093
|
+
metadata.captureId = capture.captureId;
|
|
16094
|
+
metadata.captureReason = capture.reason;
|
|
16095
|
+
metadata.sha256 = hash.digest("hex");
|
|
16096
|
+
}
|
|
16018
16097
|
try {
|
|
16019
16098
|
metadata.senders = parseChatMessageSendersJsonl(
|
|
16020
16099
|
await readFile14(chatMessageSendersFilePath(chatId), "utf-8")
|
|
@@ -16033,7 +16112,7 @@ async function uploadChatTranscript(chatId, filePath, chat) {
|
|
|
16033
16112
|
if (!isRecord(prepareBody) || typeof prepareBody.uploadUrl !== "string" && prepareBody.uploadUrl !== null) {
|
|
16034
16113
|
throw new Error("prepare failed: invalid response");
|
|
16035
16114
|
}
|
|
16036
|
-
if (prepareBody.uploadUrl === null) return;
|
|
16115
|
+
if (prepareBody.uploadUrl === null) return null;
|
|
16037
16116
|
await putTranscript(prepareBody.uploadUrl, filePath, size);
|
|
16038
16117
|
const finalizeResponse = await monolithRequest("/v1/engine/chat-transcripts/finalize", {
|
|
16039
16118
|
body: uploadRequest
|
|
@@ -16041,6 +16120,12 @@ async function uploadChatTranscript(chatId, filePath, chat) {
|
|
|
16041
16120
|
if (!finalizeResponse.ok) {
|
|
16042
16121
|
throw new Error(`finalize failed: ${finalizeResponse.status} ${await finalizeResponse.text()}`);
|
|
16043
16122
|
}
|
|
16123
|
+
const finalizeBody = await finalizeResponse.json();
|
|
16124
|
+
if (!isRecord(finalizeBody)) throw new Error("finalize failed: invalid response");
|
|
16125
|
+
if (finalizeBody.artifact === null) return null;
|
|
16126
|
+
const artifact = parseChatTranscriptArtifact(finalizeBody.artifact);
|
|
16127
|
+
if (!artifact) throw new Error("finalize failed: invalid artifact");
|
|
16128
|
+
return artifact;
|
|
16044
16129
|
}
|
|
16045
16130
|
|
|
16046
16131
|
// src/services/upload-repo-state.ts
|
|
@@ -16747,12 +16832,12 @@ var ChatService = class {
|
|
|
16747
16832
|
[...this.chats.entries()].map(([chatId, chat]) => [chatId, this.toSummary(chat)])
|
|
16748
16833
|
));
|
|
16749
16834
|
}
|
|
16750
|
-
async flushAllWorkspaceArtifacts() {
|
|
16835
|
+
async flushAllWorkspaceArtifacts(capture) {
|
|
16751
16836
|
const chatsById = new Map(
|
|
16752
16837
|
[...this.chats.entries()].map(([chatId, chat]) => [chatId, this.toSummary(chat)])
|
|
16753
16838
|
);
|
|
16754
16839
|
const [chatTranscripts, canvas, repoState, engineLogs, chatActivity] = await Promise.all([
|
|
16755
|
-
flushAllChatTranscripts(chatsById),
|
|
16840
|
+
flushAllChatTranscripts(chatsById, capture),
|
|
16756
16841
|
flushAllCanvasItems(),
|
|
16757
16842
|
flushRepoState(),
|
|
16758
16843
|
flushAllEngineLogs(),
|
|
@@ -18243,7 +18328,9 @@ function createV1Routes(deps) {
|
|
|
18243
18328
|
});
|
|
18244
18329
|
app2.post("/workspace-artifacts/flush-all", async (c) => {
|
|
18245
18330
|
try {
|
|
18246
|
-
const
|
|
18331
|
+
const body = await c.req.json().catch(() => void 0);
|
|
18332
|
+
const capture = body && typeof body.captureId === "string" && body.reason === "workspace_sleep" ? body : void 0;
|
|
18333
|
+
const result = await deps.chatService.flushAllWorkspaceArtifacts(capture);
|
|
18247
18334
|
return c.json(result);
|
|
18248
18335
|
} catch (error) {
|
|
18249
18336
|
return c.json(
|
package/package.json
CHANGED
package/workspace-sdk/index.js
CHANGED
|
@@ -45,6 +45,20 @@ function providerPath(path) {
|
|
|
45
45
|
return path;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
function providerClient(endpoint, extraOptions = () => ({})) {
|
|
49
|
+
return {
|
|
50
|
+
request: (path, options = {}) => request(endpoint, {
|
|
51
|
+
method: 'POST',
|
|
52
|
+
body: {
|
|
53
|
+
path: providerPath(path),
|
|
54
|
+
method: options.method,
|
|
55
|
+
body: options.body,
|
|
56
|
+
...extraOptions(options),
|
|
57
|
+
},
|
|
58
|
+
}),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
48
62
|
const integrations = {
|
|
49
63
|
list: () => request('/v1/engine/integrations'),
|
|
50
64
|
};
|
|
@@ -79,26 +93,9 @@ const slack = {
|
|
|
79
93
|
}),
|
|
80
94
|
};
|
|
81
95
|
|
|
82
|
-
const github =
|
|
83
|
-
request: (path, options = {}) =>
|
|
84
|
-
request('/v1/engine/github/api', {
|
|
85
|
-
method: 'POST',
|
|
86
|
-
body: { path: providerPath(path), method: options.method, body: options.body },
|
|
87
|
-
}),
|
|
88
|
-
};
|
|
96
|
+
const github = providerClient('/v1/engine/github/api');
|
|
89
97
|
|
|
90
|
-
const gitlab = {
|
|
91
|
-
request: (path, options = {}) =>
|
|
92
|
-
request('/v1/engine/gitlab/api', {
|
|
93
|
-
method: 'POST',
|
|
94
|
-
body: {
|
|
95
|
-
path: providerPath(path),
|
|
96
|
-
method: options.method,
|
|
97
|
-
body: options.body,
|
|
98
|
-
host: options.host,
|
|
99
|
-
},
|
|
100
|
-
}),
|
|
101
|
-
};
|
|
98
|
+
const gitlab = providerClient('/v1/engine/gitlab/api', (options) => ({ host: options.host }));
|
|
102
99
|
|
|
103
100
|
const sentry = {
|
|
104
101
|
request: (path) => request('/v1/engine/sentry/api', { method: 'POST', body: { path } }),
|
|
@@ -117,6 +114,8 @@ const turbopuffer = {
|
|
|
117
114
|
write: (namespace, params) => turbopufferRequest('write', namespace, params),
|
|
118
115
|
};
|
|
119
116
|
|
|
117
|
+
const planetscale = providerClient('/v1/engine/planetscale/api');
|
|
118
|
+
|
|
120
119
|
const pangramRequest = (operation, input) =>
|
|
121
120
|
request('/v1/engine/pangram', { method: 'POST', body: { operation, ...input } });
|
|
122
121
|
const pangram = {
|
|
@@ -124,5 +123,5 @@ const pangram = {
|
|
|
124
123
|
plagiarism: (text) => pangramRequest('plagiarism', { text }),
|
|
125
124
|
};
|
|
126
125
|
|
|
127
|
-
export const replicas = { integrations, plugins, linear, slack, github, gitlab, sentry, modal,
|
|
126
|
+
export const replicas = { integrations, plugins, linear, slack, github, gitlab, sentry, modal, pangram, planetscale, turbopuffer };
|
|
128
127
|
export default replicas;
|
|
@@ -137,6 +137,29 @@ describe('@replicas/sdk', () => {
|
|
|
137
137
|
server.stop(true);
|
|
138
138
|
}
|
|
139
139
|
});
|
|
140
|
+
|
|
141
|
+
test('calls PlanetScale through the workspace gateway', async () => {
|
|
142
|
+
let observed: { path: string; body: unknown } | null = null;
|
|
143
|
+
const server = Bun.serve({
|
|
144
|
+
port: 0,
|
|
145
|
+
async fetch(request) {
|
|
146
|
+
observed = { path: new URL(request.url).pathname, body: await request.json() };
|
|
147
|
+
return Response.json({ data: [] });
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
process.env.REPLICAS_MONOLITH_URL = server.url.toString().replace(/\/$/, '');
|
|
151
|
+
process.env.REPLICAS_ENGINE_SECRET = 'engine-secret';
|
|
152
|
+
process.env.REPLICAS_WORKSPACE_ID = 'workspace-1';
|
|
153
|
+
try {
|
|
154
|
+
await replicas.planetscale.request('/organizations');
|
|
155
|
+
expect(observed).toEqual({
|
|
156
|
+
path: '/v1/engine/planetscale/api',
|
|
157
|
+
body: { path: '/organizations' },
|
|
158
|
+
});
|
|
159
|
+
} finally {
|
|
160
|
+
server.stop(true);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
140
163
|
});
|
|
141
164
|
|
|
142
165
|
test('analyzes text with Pangram through the workspace gateway', async () => {
|
|
@@ -91,6 +91,14 @@ export declare const PLUGIN_CATALOG: readonly [{
|
|
|
91
91
|
readonly category: "data";
|
|
92
92
|
readonly name: "PostHog";
|
|
93
93
|
readonly description: "Manage projects, events, insights, dashboards, flags, and recordings.";
|
|
94
|
+
}, {
|
|
95
|
+
readonly id: "planetscale";
|
|
96
|
+
readonly toolkit: "planetscale";
|
|
97
|
+
readonly source: "native";
|
|
98
|
+
readonly authType: "oauth";
|
|
99
|
+
readonly category: "data";
|
|
100
|
+
readonly name: "PlanetScale";
|
|
101
|
+
readonly description: "Manage organizations, databases, branches, deploy requests, and Insights.";
|
|
94
102
|
}, {
|
|
95
103
|
readonly id: "stripe";
|
|
96
104
|
readonly toolkit: "stripe";
|
|
@@ -121,6 +129,10 @@ export declare const PLUGIN_CATALOG: readonly [{
|
|
|
121
129
|
readonly description: "Query and manage turbopuffer namespaces.";
|
|
122
130
|
}];
|
|
123
131
|
export type PluginId = (typeof PLUGIN_CATALOG)[number]['id'];
|
|
132
|
+
export type NativePluginId = Extract<(typeof PLUGIN_CATALOG)[number], {
|
|
133
|
+
source: 'native';
|
|
134
|
+
}>['id'];
|
|
135
|
+
export type ComposioPluginId = Exclude<PluginId, NativePluginId>;
|
|
124
136
|
export type PluginScope = 'organization' | 'personal';
|
|
125
137
|
export type PluginAuthType = (typeof PLUGIN_CATALOG)[number]['authType'];
|
|
126
138
|
export type PluginCategory = (typeof PLUGIN_CATALOG)[number]['category'];
|
|
@@ -133,6 +145,7 @@ export interface PluginCatalogItem {
|
|
|
133
145
|
category: PluginCategory;
|
|
134
146
|
name: string;
|
|
135
147
|
description: string;
|
|
148
|
+
source?: 'native';
|
|
136
149
|
}
|
|
137
150
|
export interface PluginConnectionSummary {
|
|
138
151
|
id: string;
|
|
@@ -210,7 +223,7 @@ export interface WorkspaceIntegrationsResponse {
|
|
|
210
223
|
native: WorkspaceNativeIntegrationStatus;
|
|
211
224
|
}
|
|
212
225
|
export interface PluginSearchRequest {
|
|
213
|
-
plugin:
|
|
226
|
+
plugin: ComposioPluginId;
|
|
214
227
|
query: string;
|
|
215
228
|
}
|
|
216
229
|
export interface PluginToolSchema {
|
|
@@ -224,14 +237,14 @@ export interface PluginSearchResponse {
|
|
|
224
237
|
tools: PluginToolSchema[];
|
|
225
238
|
}
|
|
226
239
|
export interface PluginDescribeRequest {
|
|
227
|
-
plugin:
|
|
240
|
+
plugin: ComposioPluginId;
|
|
228
241
|
tools: string[];
|
|
229
242
|
}
|
|
230
243
|
export interface PluginDescribeResponse {
|
|
231
244
|
tools: PluginToolSchema[];
|
|
232
245
|
}
|
|
233
246
|
export interface PluginExecuteRequest {
|
|
234
|
-
plugin:
|
|
247
|
+
plugin: ComposioPluginId;
|
|
235
248
|
tool: string;
|
|
236
249
|
arguments?: Record<string, unknown>;
|
|
237
250
|
}
|
|
@@ -240,4 +253,5 @@ export interface PluginExecuteResponse {
|
|
|
240
253
|
logId: string;
|
|
241
254
|
}
|
|
242
255
|
export declare function isPluginId(value: string): value is PluginId;
|
|
256
|
+
export declare function isComposioPluginId(value: string): value is ComposioPluginId;
|
|
243
257
|
export declare function isPluginConnectionStatus(value: string): value is PluginConnectionStatus;
|
|
@@ -57,6 +57,9 @@ export interface ReplicasSdk {
|
|
|
57
57
|
query<T = unknown>(namespace: string, params: Record<string, unknown>): Promise<T>;
|
|
58
58
|
write<T = unknown>(namespace: string, params: Record<string, unknown>): Promise<T>;
|
|
59
59
|
};
|
|
60
|
+
planetscale: {
|
|
61
|
+
request<T = unknown>(path: string, options?: ProviderRequestOptions): Promise<T>;
|
|
62
|
+
};
|
|
60
63
|
pangram: {
|
|
61
64
|
detect<T = unknown>(input: import('./routes/plugins').PangramAnalyzeRequest): Promise<T>;
|
|
62
65
|
plagiarism<T = unknown>(text: string): Promise<T>;
|