@persistmemory/sdk 0.1.1 → 0.2.0
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/client.d.ts +5 -0
- package/dist/http.d.ts +20 -0
- package/dist/index.cjs +193 -3
- package/dist/index.cjs.map +3 -3
- package/dist/index.js +193 -3
- package/dist/index.js.map +3 -3
- package/dist/resources/agent.d.ts +32 -0
- package/dist/resources/google.d.ts +84 -0
- package/dist/types.d.ts +91 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -238,6 +238,27 @@ var HttpClient = class {
|
|
|
238
238
|
...options ? { options } : {}
|
|
239
239
|
});
|
|
240
240
|
}
|
|
241
|
+
/** POST with a file as the body. The type describes the bytes, not JSON. */
|
|
242
|
+
async postBytes(path, bytes, contentType, query, options) {
|
|
243
|
+
return this.#request({
|
|
244
|
+
method: "POST",
|
|
245
|
+
path,
|
|
246
|
+
rawBody: bytes,
|
|
247
|
+
contentType,
|
|
248
|
+
...query ? { query } : {},
|
|
249
|
+
...options ? { options } : {}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
/** GET that returns bytes rather than JSON, for downloading a file. */
|
|
253
|
+
async getBytes(path, query, options) {
|
|
254
|
+
return this.#request({
|
|
255
|
+
method: "GET",
|
|
256
|
+
path,
|
|
257
|
+
rawResponse: true,
|
|
258
|
+
...query ? { query } : {},
|
|
259
|
+
...options ? { options } : {}
|
|
260
|
+
});
|
|
261
|
+
}
|
|
241
262
|
async patch(path, body, options) {
|
|
242
263
|
return this.#request({
|
|
243
264
|
method: "PATCH",
|
|
@@ -290,11 +311,20 @@ var HttpClient = class {
|
|
|
290
311
|
this.#fetch(url, {
|
|
291
312
|
method: request.method,
|
|
292
313
|
headers: this.#headers(request),
|
|
293
|
-
...request.body !== void 0 ? { body: JSON.stringify(request.body) } : {},
|
|
314
|
+
...request.rawBody !== void 0 ? { body: request.rawBody } : request.body !== void 0 ? { body: JSON.stringify(request.body) } : {},
|
|
294
315
|
signal: deadline.signal
|
|
295
316
|
}),
|
|
296
317
|
deadline.signal
|
|
297
318
|
);
|
|
319
|
+
if (request.rawResponse && response.ok) {
|
|
320
|
+
const disposition = response.headers.get("content-disposition") ?? "";
|
|
321
|
+
const named = /filename="([^"]+)"/.exec(disposition)?.[1];
|
|
322
|
+
return {
|
|
323
|
+
bytes: new Uint8Array(await response.arrayBuffer()),
|
|
324
|
+
contentType: response.headers.get("content-type") ?? "application/octet-stream",
|
|
325
|
+
...named ? { filename: named } : {}
|
|
326
|
+
};
|
|
327
|
+
}
|
|
298
328
|
const payload = await readBody(response);
|
|
299
329
|
if (!response.ok) throw errorFromResponse(response.status, payload, response.headers);
|
|
300
330
|
return payload;
|
|
@@ -315,9 +345,11 @@ var HttpClient = class {
|
|
|
315
345
|
return {
|
|
316
346
|
// The only place the key is ever read.
|
|
317
347
|
authorization: `Bearer ${this.#apiKey}`,
|
|
318
|
-
|
|
348
|
+
// A download route answers with the file's own type, so `*/*` rather
|
|
349
|
+
// than a promise to accept only JSON that the server would have to break.
|
|
350
|
+
accept: request.rawResponse ? "*/*" : "application/json",
|
|
319
351
|
"user-agent": this.#userAgent,
|
|
320
|
-
...request.body !== void 0 ? { "content-type": "application/json" } : {},
|
|
352
|
+
...request.rawBody !== void 0 ? { "content-type": request.contentType ?? "application/octet-stream" } : request.body !== void 0 ? { "content-type": "application/json" } : {},
|
|
321
353
|
...request.options?.idempotencyKey ? { "idempotency-key": request.options.idempotencyKey } : {}
|
|
322
354
|
};
|
|
323
355
|
}
|
|
@@ -909,6 +941,121 @@ var Conversations = class {
|
|
|
909
941
|
}
|
|
910
942
|
};
|
|
911
943
|
|
|
944
|
+
// src/resources/google.ts
|
|
945
|
+
var Google = class {
|
|
946
|
+
#http;
|
|
947
|
+
constructor(http) {
|
|
948
|
+
this.#http = http;
|
|
949
|
+
}
|
|
950
|
+
/** Files by name, newest first. Omit the query for recently changed ones. */
|
|
951
|
+
async searchDrive(params = {}, options) {
|
|
952
|
+
return this.#http.get(
|
|
953
|
+
"/api/v1/google/drive/files",
|
|
954
|
+
{
|
|
955
|
+
...params.query !== void 0 ? { query: params.query } : {},
|
|
956
|
+
...params.limit !== void 0 ? { limit: params.limit } : {}
|
|
957
|
+
},
|
|
958
|
+
options
|
|
959
|
+
);
|
|
960
|
+
}
|
|
961
|
+
async getDriveFile(fileId, options) {
|
|
962
|
+
return this.#http.get(
|
|
963
|
+
`/api/v1/google/drive/files/${encodeURIComponent(fileId)}`,
|
|
964
|
+
void 0,
|
|
965
|
+
options
|
|
966
|
+
);
|
|
967
|
+
}
|
|
968
|
+
/**
|
|
969
|
+
* The bytes of a Drive file.
|
|
970
|
+
*
|
|
971
|
+
* A Google Doc, Sheet or Slide holds no bytes of its own and is exported on
|
|
972
|
+
* the way - a document as PDF, a spreadsheet as CSV - so `filename` comes
|
|
973
|
+
* back describing what it BECAME. Writing it under the id instead produces a
|
|
974
|
+
* file nothing will open.
|
|
975
|
+
*/
|
|
976
|
+
async downloadDriveFile(fileId, options) {
|
|
977
|
+
return this.#http.getBytes(
|
|
978
|
+
`/api/v1/google/drive/files/${encodeURIComponent(fileId)}/content`,
|
|
979
|
+
void 0,
|
|
980
|
+
options
|
|
981
|
+
);
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Writes a file into the user's Drive.
|
|
985
|
+
*
|
|
986
|
+
* Needs one of the Drive write permissions on their connection. A read-only
|
|
987
|
+
* grant is refused by Google, and the error names the missing permission
|
|
988
|
+
* rather than reporting a failed upload - one is fixed with a checkbox and
|
|
989
|
+
* the other sends somebody looking for a bug.
|
|
990
|
+
*/
|
|
991
|
+
async saveToDrive(params, options) {
|
|
992
|
+
return this.#http.postBytes(
|
|
993
|
+
"/api/v1/google/drive/files",
|
|
994
|
+
params.bytes,
|
|
995
|
+
params.contentType ?? "application/octet-stream",
|
|
996
|
+
{
|
|
997
|
+
name: params.name,
|
|
998
|
+
...params.folderId !== void 0 ? { folderId: params.folderId } : {}
|
|
999
|
+
},
|
|
1000
|
+
options
|
|
1001
|
+
);
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Recent messages - senders, subjects and a one-line preview, never bodies.
|
|
1005
|
+
*
|
|
1006
|
+
* `query` is Gmail's own syntax passed through as written: `from:priya`,
|
|
1007
|
+
* `has:attachment`, `newer_than:7d`. It selects within the connected mailbox
|
|
1008
|
+
* and cannot reach another one.
|
|
1009
|
+
*/
|
|
1010
|
+
async searchMail(params = {}, options) {
|
|
1011
|
+
return this.#http.get(
|
|
1012
|
+
"/api/v1/google/mail",
|
|
1013
|
+
{
|
|
1014
|
+
...params.query !== void 0 ? { query: params.query } : {},
|
|
1015
|
+
...params.limit !== void 0 ? { limit: params.limit } : {}
|
|
1016
|
+
},
|
|
1017
|
+
options
|
|
1018
|
+
);
|
|
1019
|
+
}
|
|
1020
|
+
/** One message, with its body and the names of what is attached. */
|
|
1021
|
+
async readMail(messageId, options) {
|
|
1022
|
+
return this.#http.get(
|
|
1023
|
+
`/api/v1/google/mail/${encodeURIComponent(messageId)}`,
|
|
1024
|
+
void 0,
|
|
1025
|
+
options
|
|
1026
|
+
);
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* The bytes of one attachment.
|
|
1030
|
+
*
|
|
1031
|
+
* Separate from `readMail` so listing a mailbox never drags attachments
|
|
1032
|
+
* across the network: a message with a 40 MB deck should not cost 40 MB to
|
|
1033
|
+
* summarise.
|
|
1034
|
+
*/
|
|
1035
|
+
async downloadAttachment(messageId, attachmentId, options) {
|
|
1036
|
+
return this.#http.getBytes(
|
|
1037
|
+
`/api/v1/google/mail/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(attachmentId)}`,
|
|
1038
|
+
void 0,
|
|
1039
|
+
options
|
|
1040
|
+
);
|
|
1041
|
+
}
|
|
1042
|
+
/** Sends as the connected account. Needs the send permission. */
|
|
1043
|
+
async sendMail(params, options) {
|
|
1044
|
+
return this.#http.post("/api/v1/google/mail/send", params, options);
|
|
1045
|
+
}
|
|
1046
|
+
/** People in the user's contacts. Omit the query to list them. */
|
|
1047
|
+
async contacts(params = {}, options) {
|
|
1048
|
+
return this.#http.get(
|
|
1049
|
+
"/api/v1/google/contacts",
|
|
1050
|
+
{
|
|
1051
|
+
...params.query !== void 0 ? { query: params.query } : {},
|
|
1052
|
+
...params.limit !== void 0 ? { limit: params.limit } : {}
|
|
1053
|
+
},
|
|
1054
|
+
options
|
|
1055
|
+
);
|
|
1056
|
+
}
|
|
1057
|
+
};
|
|
1058
|
+
|
|
912
1059
|
// src/resources/integrations.ts
|
|
913
1060
|
var Integrations = class {
|
|
914
1061
|
#http;
|
|
@@ -995,6 +1142,44 @@ var Health = class {
|
|
|
995
1142
|
}
|
|
996
1143
|
};
|
|
997
1144
|
|
|
1145
|
+
// src/resources/agent.ts
|
|
1146
|
+
var Agent = class {
|
|
1147
|
+
#http;
|
|
1148
|
+
constructor(http) {
|
|
1149
|
+
this.#http = http;
|
|
1150
|
+
}
|
|
1151
|
+
/** The row, including whether it finished and how large the result is. */
|
|
1152
|
+
async request(id, options) {
|
|
1153
|
+
return this.#http.get(
|
|
1154
|
+
`/api/v1/agent/request/${encodeURIComponent(id)}`,
|
|
1155
|
+
void 0,
|
|
1156
|
+
options
|
|
1157
|
+
);
|
|
1158
|
+
}
|
|
1159
|
+
/**
|
|
1160
|
+
* A short-lived link to the bytes of a finished request.
|
|
1161
|
+
*
|
|
1162
|
+
* Returns the URL rather than the file, and that is a deliberate limit of
|
|
1163
|
+
* this package rather than an oversight. The transport under every other
|
|
1164
|
+
* method parses JSON, retries, and attaches the API key; none of those is
|
|
1165
|
+
* right for a hundred-megabyte binary body, and building a second request
|
|
1166
|
+
* path inside the SDK to serve one method is how a client ends up with two
|
|
1167
|
+
* retry policies that differ only during an outage. Fetch the URL with
|
|
1168
|
+
* whatever already streams in your runtime - it needs no credential, which
|
|
1169
|
+
* is the whole reason it is signed.
|
|
1170
|
+
*
|
|
1171
|
+
* Treat the URL as the file. It is a bearer credential for exactly one
|
|
1172
|
+
* object, it expires in minutes, and it should not be logged or stored.
|
|
1173
|
+
*/
|
|
1174
|
+
async downloadLink(id, options) {
|
|
1175
|
+
return this.#http.get(
|
|
1176
|
+
`/api/v1/agent/request/${encodeURIComponent(id)}/download`,
|
|
1177
|
+
void 0,
|
|
1178
|
+
options
|
|
1179
|
+
);
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1182
|
+
|
|
998
1183
|
// src/client.ts
|
|
999
1184
|
var PersistMemory = class {
|
|
1000
1185
|
memories;
|
|
@@ -1008,7 +1193,10 @@ var PersistMemory = class {
|
|
|
1008
1193
|
conflicts;
|
|
1009
1194
|
conversations;
|
|
1010
1195
|
integrations;
|
|
1196
|
+
/** Drive, mail and contacts on the user's connected Google account. */
|
|
1197
|
+
google;
|
|
1011
1198
|
health;
|
|
1199
|
+
agent;
|
|
1012
1200
|
#http;
|
|
1013
1201
|
constructor(options) {
|
|
1014
1202
|
this.#http = new HttpClient(options);
|
|
@@ -1023,7 +1211,9 @@ var PersistMemory = class {
|
|
|
1023
1211
|
this.conflicts = new Conflicts(this.#http);
|
|
1024
1212
|
this.conversations = new Conversations(this.#http);
|
|
1025
1213
|
this.integrations = new Integrations(this.#http);
|
|
1214
|
+
this.google = new Google(this.#http);
|
|
1026
1215
|
this.health = new Health(this.#http);
|
|
1216
|
+
this.agent = new Agent(this.#http);
|
|
1027
1217
|
}
|
|
1028
1218
|
/**
|
|
1029
1219
|
* An escape hatch for an endpoint this package has not caught up with.
|