@mindstudio-ai/agent 0.1.107 → 0.1.109
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/cli.js +348 -59
- package/dist/index.d.ts +259 -1
- package/dist/index.js +335 -44
- package/dist/index.js.map +1 -1
- package/dist/postinstall.js +348 -59
- package/llms.txt +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -102,9 +102,12 @@ function runWithContext(ctx, fn) {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
// src/db-ws.ts
|
|
105
|
-
var
|
|
105
|
+
var DB_WS_SUBPROTOCOL = "ms-db-v2";
|
|
106
|
+
var WS_ACK_TIMEOUT_MS = 2e4;
|
|
107
|
+
var WS_IDLE_TIMEOUT_MS = 3e5;
|
|
106
108
|
var WS_OPEN_TIMEOUT_MS = 5e3;
|
|
107
109
|
var WS_OPEN = 1;
|
|
110
|
+
var WS_CHUNK_CHARS = 256 * 1024;
|
|
108
111
|
var WS_MAX_FRAME_CHARS = 9e5;
|
|
109
112
|
var DbWsTransportError = class extends Error {
|
|
110
113
|
constructor(message, sent = false) {
|
|
@@ -117,13 +120,86 @@ function isReadOnlySql(sql) {
|
|
|
117
120
|
const head = sql.trimStart().slice(0, 8).toUpperCase();
|
|
118
121
|
return head.startsWith("SELECT") || head.startsWith("PRAGMA") || head.startsWith("EXPLAIN");
|
|
119
122
|
}
|
|
120
|
-
var
|
|
123
|
+
var conn = null;
|
|
121
124
|
var opening = null;
|
|
122
125
|
var idCounter = 0;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
126
|
+
function clearPendingTimer(p) {
|
|
127
|
+
if (p.timer !== null) {
|
|
128
|
+
clearTimeout(p.timer);
|
|
129
|
+
p.timer = null;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function forget(self, id) {
|
|
133
|
+
self.pending.delete(id);
|
|
134
|
+
self.inbound.delete(id);
|
|
135
|
+
if (self.retired && self.pending.size === 0) {
|
|
136
|
+
try {
|
|
137
|
+
self.ws.close();
|
|
138
|
+
} catch {
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function retire(self, reason) {
|
|
143
|
+
if (self.retired) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
self.retired = true;
|
|
147
|
+
if (conn === self) {
|
|
148
|
+
conn = null;
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
console.warn(
|
|
152
|
+
`[mindstudio] db: retiring WebSocket after ${reason}; next query reconnects.`
|
|
153
|
+
);
|
|
154
|
+
} catch {
|
|
155
|
+
}
|
|
156
|
+
if (self.pending.size === 0) {
|
|
157
|
+
try {
|
|
158
|
+
self.ws.close();
|
|
159
|
+
} catch {
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function armIdleTimer(self, id, p) {
|
|
164
|
+
clearPendingTimer(p);
|
|
165
|
+
p.timer = setTimeout(() => {
|
|
166
|
+
forget(self, id);
|
|
167
|
+
retire(self, "a reply went silent");
|
|
168
|
+
p.reject(new DbWsTransportError("ws reply went silent", true));
|
|
169
|
+
}, WS_IDLE_TIMEOUT_MS);
|
|
170
|
+
}
|
|
171
|
+
function deliver(self, msg) {
|
|
172
|
+
const p = self.pending.get(msg.id);
|
|
173
|
+
if (!p) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
clearPendingTimer(p);
|
|
177
|
+
forget(self, msg.id);
|
|
178
|
+
if (msg.error) {
|
|
179
|
+
p.reject(
|
|
180
|
+
new MindStudioError(
|
|
181
|
+
`[db] ${msg.error.message || "Database query failed"}`,
|
|
182
|
+
msg.error.code || "db_query_error",
|
|
183
|
+
400,
|
|
184
|
+
msg.error
|
|
185
|
+
)
|
|
186
|
+
);
|
|
187
|
+
} else {
|
|
188
|
+
p.resolve(msg.results);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function failTransport(self, id, err) {
|
|
192
|
+
const p = self.pending.get(id);
|
|
193
|
+
if (!p) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
clearPendingTimer(p);
|
|
197
|
+
forget(self, id);
|
|
198
|
+
p.reject(err);
|
|
199
|
+
}
|
|
200
|
+
function getOrOpen(url, token) {
|
|
201
|
+
if (conn && !conn.retired && conn.ws.readyState === WS_OPEN) {
|
|
202
|
+
return Promise.resolve(conn);
|
|
127
203
|
}
|
|
128
204
|
if (opening) {
|
|
129
205
|
return opening;
|
|
@@ -136,17 +212,22 @@ function getOrOpen(url) {
|
|
|
136
212
|
}
|
|
137
213
|
opening = new Promise((resolve, reject) => {
|
|
138
214
|
let ws;
|
|
215
|
+
let self = null;
|
|
139
216
|
const fail = (err) => {
|
|
140
217
|
clearTimeout(openTimer);
|
|
141
|
-
if (
|
|
142
|
-
|
|
218
|
+
if (self) {
|
|
219
|
+
self.retired = true;
|
|
220
|
+
if (conn === self) {
|
|
221
|
+
conn = null;
|
|
222
|
+
}
|
|
223
|
+
for (const [, p] of self.pending) {
|
|
224
|
+
clearPendingTimer(p);
|
|
225
|
+
p.reject(new DbWsTransportError(err.message, true));
|
|
226
|
+
}
|
|
227
|
+
self.pending.clear();
|
|
228
|
+
self.inbound.clear();
|
|
143
229
|
}
|
|
144
230
|
opening = null;
|
|
145
|
-
for (const [, p] of pending) {
|
|
146
|
-
clearTimeout(p.timer);
|
|
147
|
-
p.reject(new DbWsTransportError(err.message, true));
|
|
148
|
-
}
|
|
149
|
-
pending.clear();
|
|
150
231
|
reject(err);
|
|
151
232
|
};
|
|
152
233
|
const openTimer = setTimeout(() => {
|
|
@@ -157,16 +238,26 @@ function getOrOpen(url) {
|
|
|
157
238
|
fail(new DbWsTransportError("ws open timed out"));
|
|
158
239
|
}, WS_OPEN_TIMEOUT_MS);
|
|
159
240
|
try {
|
|
160
|
-
ws = new WebSocketCtor(url);
|
|
241
|
+
ws = new WebSocketCtor(url, ["auth", token, DB_WS_SUBPROTOCOL]);
|
|
161
242
|
} catch (err) {
|
|
162
243
|
fail(new DbWsTransportError(err?.message || "ws construct failed"));
|
|
163
244
|
return;
|
|
164
245
|
}
|
|
246
|
+
self = {
|
|
247
|
+
ws,
|
|
248
|
+
pending: /* @__PURE__ */ new Map(),
|
|
249
|
+
chunked: false,
|
|
250
|
+
inbound: /* @__PURE__ */ new Map(),
|
|
251
|
+
acksSeen: false,
|
|
252
|
+
retired: false
|
|
253
|
+
};
|
|
254
|
+
const c = self;
|
|
165
255
|
ws.onopen = () => {
|
|
166
256
|
clearTimeout(openTimer);
|
|
167
|
-
|
|
257
|
+
c.chunked = ws.protocol === DB_WS_SUBPROTOCOL;
|
|
258
|
+
conn = c;
|
|
168
259
|
opening = null;
|
|
169
|
-
resolve(
|
|
260
|
+
resolve(c);
|
|
170
261
|
};
|
|
171
262
|
ws.onmessage = (ev) => {
|
|
172
263
|
let msg;
|
|
@@ -177,26 +268,54 @@ function getOrOpen(url) {
|
|
|
177
268
|
} catch {
|
|
178
269
|
return;
|
|
179
270
|
}
|
|
180
|
-
if (!msg || msg.
|
|
271
|
+
if (!msg || msg.id == null) {
|
|
181
272
|
return;
|
|
182
273
|
}
|
|
183
|
-
|
|
184
|
-
|
|
274
|
+
if (msg.t === "db-ack") {
|
|
275
|
+
c.acksSeen = true;
|
|
276
|
+
const p = c.pending.get(msg.id);
|
|
277
|
+
if (p && !p.acked) {
|
|
278
|
+
p.acked = true;
|
|
279
|
+
armIdleTimer(c, msg.id, p);
|
|
280
|
+
}
|
|
185
281
|
return;
|
|
186
282
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
)
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
283
|
+
if (msg.t === "db-chunk") {
|
|
284
|
+
const p = c.pending.get(msg.id);
|
|
285
|
+
if (!p || typeof msg.data !== "string") {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
const parts = c.inbound.get(msg.id);
|
|
289
|
+
if (parts) {
|
|
290
|
+
parts.push(msg.data);
|
|
291
|
+
} else {
|
|
292
|
+
c.inbound.set(msg.id, [msg.data]);
|
|
293
|
+
}
|
|
294
|
+
armIdleTimer(c, msg.id, p);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
if (msg.t === "db-end") {
|
|
298
|
+
const parts = c.inbound.get(msg.id);
|
|
299
|
+
if (!parts) {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
c.inbound.delete(msg.id);
|
|
303
|
+
let assembled;
|
|
304
|
+
try {
|
|
305
|
+
assembled = JSON.parse(parts.join(""));
|
|
306
|
+
} catch {
|
|
307
|
+
failTransport(
|
|
308
|
+
c,
|
|
309
|
+
msg.id,
|
|
310
|
+
new DbWsTransportError("chunked reply did not parse", true)
|
|
311
|
+
);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
deliver(c, assembled);
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
if (msg.t === "db-result") {
|
|
318
|
+
deliver(c, msg);
|
|
200
319
|
}
|
|
201
320
|
};
|
|
202
321
|
ws.onerror = () => fail(new DbWsTransportError("ws error"));
|
|
@@ -204,28 +323,59 @@ function getOrOpen(url) {
|
|
|
204
323
|
});
|
|
205
324
|
return opening;
|
|
206
325
|
}
|
|
326
|
+
function* outboundFrames(id, json) {
|
|
327
|
+
if (json.length <= WS_CHUNK_CHARS) {
|
|
328
|
+
yield json;
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
let seq = 0;
|
|
332
|
+
for (let offset = 0; offset < json.length; offset += WS_CHUNK_CHARS) {
|
|
333
|
+
yield JSON.stringify({
|
|
334
|
+
t: "db-chunk",
|
|
335
|
+
id,
|
|
336
|
+
seq: seq++,
|
|
337
|
+
data: json.slice(offset, offset + WS_CHUNK_CHARS)
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
yield JSON.stringify({ t: "db-end", id });
|
|
341
|
+
}
|
|
207
342
|
async function executeDbBatchOverWs(url, token, databaseId, queries) {
|
|
208
343
|
const id = ++idCounter;
|
|
209
344
|
const frame = JSON.stringify({ t: "db", id, token, databaseId, queries });
|
|
210
|
-
|
|
345
|
+
const self = await getOrOpen(url, token);
|
|
346
|
+
if (!self.chunked && frame.length > WS_MAX_FRAME_CHARS) {
|
|
211
347
|
throw new DbWsTransportError("payload too large for ws");
|
|
212
348
|
}
|
|
213
|
-
const ws = await getOrOpen(url);
|
|
214
349
|
return await new Promise((resolve, reject) => {
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
350
|
+
const pending = { resolve, reject, timer: null, acked: false };
|
|
351
|
+
if (self.acksSeen) {
|
|
352
|
+
pending.timer = setTimeout(() => {
|
|
353
|
+
forget(self, id);
|
|
354
|
+
retire(self, "a request went unacknowledged");
|
|
355
|
+
reject(new DbWsTransportError("ws ack timed out", true));
|
|
356
|
+
}, WS_ACK_TIMEOUT_MS);
|
|
357
|
+
} else {
|
|
358
|
+
armIdleTimer(self, id, pending);
|
|
359
|
+
}
|
|
360
|
+
self.pending.set(id, pending);
|
|
361
|
+
let started = false;
|
|
362
|
+
let complete = false;
|
|
220
363
|
try {
|
|
221
|
-
|
|
364
|
+
for (const out of outboundFrames(id, frame)) {
|
|
365
|
+
self.ws.send(out);
|
|
366
|
+
started = true;
|
|
367
|
+
}
|
|
368
|
+
complete = true;
|
|
222
369
|
} catch (err) {
|
|
223
|
-
|
|
224
|
-
|
|
370
|
+
clearPendingTimer(pending);
|
|
371
|
+
forget(self, id);
|
|
372
|
+
if (started) {
|
|
373
|
+
retire(self, "a partial request upload failed");
|
|
374
|
+
}
|
|
225
375
|
reject(
|
|
226
376
|
new DbWsTransportError(
|
|
227
377
|
`ws send failed: ${err?.message || "unknown"}`,
|
|
228
|
-
|
|
378
|
+
complete
|
|
229
379
|
)
|
|
230
380
|
);
|
|
231
381
|
}
|
|
@@ -2442,6 +2592,7 @@ function toBase64(content) {
|
|
|
2442
2592
|
typeof content === "string" ? Buffer.from(content) : content
|
|
2443
2593
|
).toString("base64");
|
|
2444
2594
|
}
|
|
2595
|
+
var PRESIGN_THRESHOLD = 4 * 1024 * 1024;
|
|
2445
2596
|
function extensionFor(filename) {
|
|
2446
2597
|
if (!filename) {
|
|
2447
2598
|
return "";
|
|
@@ -2469,16 +2620,73 @@ var Store = class {
|
|
|
2469
2620
|
const ext = extensionFor(options?.filename);
|
|
2470
2621
|
const key = options?.key ?? (options?.contentAddressed ? `${createHash("sha256").update(content).digest("hex")}${ext}` : `${randomUUID()}${ext}`);
|
|
2471
2622
|
const cacheControl = options?.cacheControl ?? (!options?.key && this._access === "public" ? "public, max-age=31536000, immutable" : void 0);
|
|
2623
|
+
const bytes = typeof content === "string" ? Buffer.from(content) : content;
|
|
2624
|
+
if (bytes.byteLength >= PRESIGN_THRESHOLD) {
|
|
2625
|
+
return this._putPresigned(bytes, key, {
|
|
2626
|
+
...options?.contentType ? { contentType: options.contentType } : {},
|
|
2627
|
+
...cacheControl ? { cacheControl } : {}
|
|
2628
|
+
});
|
|
2629
|
+
}
|
|
2472
2630
|
const meta = await this._call("put", {
|
|
2473
2631
|
store: this._store,
|
|
2474
2632
|
access: this._access,
|
|
2475
2633
|
key,
|
|
2476
|
-
body: toBase64(
|
|
2634
|
+
body: toBase64(bytes),
|
|
2477
2635
|
...options?.contentType ? { contentType: options.contentType } : {},
|
|
2478
2636
|
...cacheControl ? { cacheControl } : {}
|
|
2479
2637
|
});
|
|
2480
2638
|
return this._toFile(key, meta);
|
|
2481
2639
|
}
|
|
2640
|
+
/**
|
|
2641
|
+
* Large-content half of {@link put}: mint a presigned POST scoped to exactly
|
|
2642
|
+
* these bytes and send them direct to storage — the JSON transport's body
|
|
2643
|
+
* limit never sees them. Same result contract as the small path; the final
|
|
2644
|
+
* `head` keeps the returned metadata honest (server-observed size/type/time).
|
|
2645
|
+
*/
|
|
2646
|
+
async _putPresigned(bytes, key, options) {
|
|
2647
|
+
const res = await this._call("create-upload", {
|
|
2648
|
+
store: this._store,
|
|
2649
|
+
access: this._access,
|
|
2650
|
+
key,
|
|
2651
|
+
maxSize: bytes.byteLength,
|
|
2652
|
+
...options.contentType ? { contentType: options.contentType } : {},
|
|
2653
|
+
...options.cacheControl ? { cacheControl: options.cacheControl } : {}
|
|
2654
|
+
});
|
|
2655
|
+
const form = new FormData();
|
|
2656
|
+
for (const [k, v] of Object.entries(
|
|
2657
|
+
res.uploadFields
|
|
2658
|
+
)) {
|
|
2659
|
+
form.append(k, v);
|
|
2660
|
+
}
|
|
2661
|
+
const view = new Uint8Array(
|
|
2662
|
+
bytes.buffer,
|
|
2663
|
+
bytes.byteOffset,
|
|
2664
|
+
bytes.byteLength
|
|
2665
|
+
);
|
|
2666
|
+
form.append(
|
|
2667
|
+
"file",
|
|
2668
|
+
new Blob([view], options.contentType ? { type: options.contentType } : void 0)
|
|
2669
|
+
);
|
|
2670
|
+
const upload = await fetch(res.uploadUrl, {
|
|
2671
|
+
method: "POST",
|
|
2672
|
+
body: form
|
|
2673
|
+
});
|
|
2674
|
+
if (!upload.ok) {
|
|
2675
|
+
const errorText = await upload.text().catch(() => "");
|
|
2676
|
+
throw new MindStudioError(
|
|
2677
|
+
`Upload failed: ${upload.status} ${upload.statusText}${errorText ? ` \u2014 ${errorText.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim().slice(0, 200)}` : ""}`,
|
|
2678
|
+
"upload_error",
|
|
2679
|
+
upload.status,
|
|
2680
|
+
errorText || void 0
|
|
2681
|
+
);
|
|
2682
|
+
}
|
|
2683
|
+
const meta = await this._call("head", {
|
|
2684
|
+
store: this._store,
|
|
2685
|
+
access: this._access,
|
|
2686
|
+
key
|
|
2687
|
+
});
|
|
2688
|
+
return this._toFile(key, meta);
|
|
2689
|
+
}
|
|
2482
2690
|
/** Read an object's bytes (backend / trusted context). */
|
|
2483
2691
|
async get(key) {
|
|
2484
2692
|
const res = await this._call("get", {
|
|
@@ -2814,6 +3022,50 @@ function createAnalytics(call) {
|
|
|
2814
3022
|
};
|
|
2815
3023
|
}
|
|
2816
3024
|
|
|
3025
|
+
// src/email/index.ts
|
|
3026
|
+
var iso = (v) => v === void 0 ? void 0 : v instanceof Date ? v.toISOString() : v;
|
|
3027
|
+
function createEmail(call) {
|
|
3028
|
+
return {
|
|
3029
|
+
stats(options) {
|
|
3030
|
+
return call("stats", {
|
|
3031
|
+
start: iso(options?.start),
|
|
3032
|
+
end: iso(options?.end),
|
|
3033
|
+
buckets: options?.buckets
|
|
3034
|
+
});
|
|
3035
|
+
},
|
|
3036
|
+
messages(options) {
|
|
3037
|
+
return call("messages", {
|
|
3038
|
+
...options,
|
|
3039
|
+
start: iso(options?.start),
|
|
3040
|
+
end: iso(options?.end)
|
|
3041
|
+
});
|
|
3042
|
+
},
|
|
3043
|
+
message(messageId) {
|
|
3044
|
+
return call("message", { messageId });
|
|
3045
|
+
},
|
|
3046
|
+
batches(options) {
|
|
3047
|
+
return call("batches", {
|
|
3048
|
+
start: iso(options?.start),
|
|
3049
|
+
end: iso(options?.end),
|
|
3050
|
+
limit: options?.limit,
|
|
3051
|
+
offset: options?.offset
|
|
3052
|
+
});
|
|
3053
|
+
},
|
|
3054
|
+
batch(batchId) {
|
|
3055
|
+
return call("batch", { batchId });
|
|
3056
|
+
},
|
|
3057
|
+
suppressions(options) {
|
|
3058
|
+
return call("suppressions", options ?? {});
|
|
3059
|
+
},
|
|
3060
|
+
suppress(email2) {
|
|
3061
|
+
return call("suppress", { email: email2 });
|
|
3062
|
+
},
|
|
3063
|
+
unsuppress(email2) {
|
|
3064
|
+
return call("unsuppress", { email: email2 });
|
|
3065
|
+
}
|
|
3066
|
+
};
|
|
3067
|
+
}
|
|
3068
|
+
|
|
2817
3069
|
// src/task/index.ts
|
|
2818
3070
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2819
3071
|
|
|
@@ -5526,6 +5778,7 @@ var MindStudioAgent = class {
|
|
|
5526
5778
|
_dataSources;
|
|
5527
5779
|
_voice;
|
|
5528
5780
|
_analytics;
|
|
5781
|
+
_email;
|
|
5529
5782
|
/** @internal Auth type — 'internal' for CALLBACK_TOKEN (managed mode), 'apiKey' otherwise. */
|
|
5530
5783
|
_authType;
|
|
5531
5784
|
/** @internal Usage source sent on step executions (from MINDSTUDIO_REQUEST_SOURCE).
|
|
@@ -6570,6 +6823,24 @@ var MindStudioAgent = class {
|
|
|
6570
6823
|
this._analyticsRequest.bind(this)
|
|
6571
6824
|
);
|
|
6572
6825
|
}
|
|
6826
|
+
/**
|
|
6827
|
+
* Outbound email: the per-recipient delivery log, blast stats, and this app's
|
|
6828
|
+
* unsubscribe list. Sending is the `sendEmail` action, not this namespace.
|
|
6829
|
+
*
|
|
6830
|
+
* @example
|
|
6831
|
+
* ```ts
|
|
6832
|
+
* import { email } from '@mindstudio-ai/agent';
|
|
6833
|
+
*
|
|
6834
|
+
* // A support lookup: did this person get their mail?
|
|
6835
|
+
* const { messages } = await email.messages({ recipient: 'a@b.com' });
|
|
6836
|
+
*
|
|
6837
|
+
* // How did the August newsletter do?
|
|
6838
|
+
* const blast = await email.batch('newsletter-2026-08');
|
|
6839
|
+
* ```
|
|
6840
|
+
*/
|
|
6841
|
+
get email() {
|
|
6842
|
+
return this._email ??= createEmail(this._emailRequest.bind(this));
|
|
6843
|
+
}
|
|
6573
6844
|
/**
|
|
6574
6845
|
* Jewel surfaces: arrival-shaped triggers (`propose`) and the app-native
|
|
6575
6846
|
* approval queue (`queue.list` / `queue.resolve`). See {@link JewelsApi}.
|
|
@@ -6708,6 +6979,18 @@ var MindStudioAgent = class {
|
|
|
6708
6979
|
* of surfacing as empty data. Deliberately single-shot and scoped to this
|
|
6709
6980
|
* namespace — the other brokered transports keep their semantics.
|
|
6710
6981
|
*/
|
|
6982
|
+
/**
|
|
6983
|
+
* Brokered email transport. No 429 retry, unlike analytics: this namespace
|
|
6984
|
+
* carries writes (suppress / unsuppress), and silently retrying a mutation is a
|
|
6985
|
+
* different risk from retrying an idempotent read. A caller that wants one can
|
|
6986
|
+
* retry a read itself.
|
|
6987
|
+
*/
|
|
6988
|
+
async _emailRequest(op, body) {
|
|
6989
|
+
return this._brokeredRequest("email", op, body, {
|
|
6990
|
+
fallbackMessage: "Email API call failed",
|
|
6991
|
+
fallbackCode: "email_error"
|
|
6992
|
+
});
|
|
6993
|
+
}
|
|
6711
6994
|
async _analyticsRequest(op, body) {
|
|
6712
6995
|
const call = () => this._brokeredRequest("analytics", op, body, {
|
|
6713
6996
|
fallbackMessage: "Analytics read failed",
|
|
@@ -7612,6 +7895,13 @@ var analytics = new Proxy({}, {
|
|
|
7612
7895
|
return typeof value === "function" ? value.bind(target) : value;
|
|
7613
7896
|
}
|
|
7614
7897
|
});
|
|
7898
|
+
var email = new Proxy({}, {
|
|
7899
|
+
get(_, prop) {
|
|
7900
|
+
const target = mindstudio.email;
|
|
7901
|
+
const value = Reflect.get(target, prop, target);
|
|
7902
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
7903
|
+
}
|
|
7904
|
+
});
|
|
7615
7905
|
var session = new Proxy(
|
|
7616
7906
|
{},
|
|
7617
7907
|
{
|
|
@@ -7640,6 +7930,7 @@ export {
|
|
|
7640
7930
|
db,
|
|
7641
7931
|
index_default as default,
|
|
7642
7932
|
defineJewel,
|
|
7933
|
+
email,
|
|
7643
7934
|
files,
|
|
7644
7935
|
getRequestContext,
|
|
7645
7936
|
mindstudio,
|