@rei-standard/amsg-server 2.6.0-next.20 → 2.6.0-next.21
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 +154 -7
- package/dist/adapters/d1.d.ts +28 -0
- package/dist/adapters/interface.d.ts +46 -5
- package/dist/adapters/neon.d.ts +7 -1
- package/dist/adapters/schema.d.ts +16 -0
- package/dist/{chunk-V6NZQ22S.cjs → chunk-7NMQFTDJ.cjs} +5 -1
- package/dist/{chunk-5FXVSC5O.mjs → chunk-GN44PST5.mjs} +5 -1
- package/dist/{chunk-HTGYGGUH.mjs → chunk-KOJQVOYS.mjs} +1125 -276
- package/dist/{chunk-WOXSQBAM.cjs → chunk-QHVID3V2.cjs} +1114 -265
- package/dist/cloudflare.cjs +7 -3
- package/dist/cloudflare.d.ts +1 -0
- package/dist/cloudflare.mjs +6 -2
- package/dist/index.cjs +40 -28
- package/dist/index.d.cts +20 -2
- package/dist/index.d.ts +20 -2
- package/dist/index.mjs +16 -4
- package/dist/lib/client-state-store.d.ts +19 -0
- package/dist/lib/errors.d.ts +129 -7
- package/dist/lib/message-processor.d.ts +18 -1
- package/dist/lib/outbox-store.d.ts +62 -0
- package/dist/lib/push-subscription-store.d.ts +23 -0
- package/dist/lib/request.d.ts +47 -0
- package/dist/lib/result-emitter.d.ts +54 -0
- package/dist/lib/run-tick.d.ts +9 -0
- package/dist/lib/task-projection.d.ts +8 -3
- package/dist/lib/validation.d.ts +35 -0
- package/dist/{neon-U6TQFKMJ.cjs → neon-KP2CPA57.cjs} +23 -15
- package/dist/{neon-Y4KEZO5C.mjs → neon-ZIMHALYI.mjs} +14 -6
- package/dist/{pg-GWJZBWAM.mjs → pg-QGC2XHUT.mjs} +13 -5
- package/dist/{pg-B324Q2R4.cjs → pg-RZPQGXR3.cjs} +22 -14
- package/dist/single-user.d.ts +1 -0
- package/package.json +2 -2
package/dist/cloudflare.cjs
CHANGED
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
var _chunkWOXSQBAMcjs = require('./chunk-WOXSQBAM.cjs');
|
|
28
|
-
require('./chunk-V6NZQ22S.cjs');
|
|
29
27
|
|
|
30
28
|
|
|
29
|
+
var _chunkQHVID3V2cjs = require('./chunk-QHVID3V2.cjs');
|
|
30
|
+
require('./chunk-7NMQFTDJ.cjs');
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
|
|
@@ -52,4 +52,8 @@ require('./chunk-V6NZQ22S.cjs');
|
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
exports.DEFAULT_MAX_REQUEST_BODY_BYTES = _chunkQHVID3V2cjs.DEFAULT_MAX_REQUEST_BODY_BYTES; exports.MAX_PUSH_PAYLOAD_BYTES = _chunkQHVID3V2cjs.MAX_PUSH_PAYLOAD_BYTES; exports.NonRetryableError = _chunkQHVID3V2cjs.NonRetryableError; exports.PUSH_ENVELOPE_RESERVED_BYTES = _chunkQHVID3V2cjs.PUSH_ENVELOPE_RESERVED_BYTES; exports.SCHEMA_VERSION = _chunkQHVID3V2cjs.SCHEMA_VERSION; exports.WEB_PUSH_ENCRYPTION_OVERHEAD_BYTES = _chunkQHVID3V2cjs.WEB_PUSH_ENCRYPTION_OVERHEAD_BYTES; exports.WEB_PUSH_MAX_BODY_BYTES = _chunkQHVID3V2cjs.WEB_PUSH_MAX_BODY_BYTES; exports.advanceOccurrence = _chunkQHVID3V2cjs.advanceOccurrence; exports.createD1Adapter = _chunkQHVID3V2cjs.createD1Adapter; exports.createSingleUserCloudflareWorker = _chunkQHVID3V2cjs.createSingleUserCloudflareWorker; exports.createSingleUserServer = _chunkQHVID3V2cjs.createSingleUserServer; exports.createWebCryptoWebPush = _chunkQHVID3V2cjs.createWebCryptoWebPush; exports.decryptFromStorage = _chunkQHVID3V2cjs.decryptFromStorage; exports.decryptPayload = _chunkQHVID3V2cjs.decryptPayload; exports.deriveUserEncryptionKey = _chunkQHVID3V2cjs.deriveUserEncryptionKey; exports.encryptForStorage = _chunkQHVID3V2cjs.encryptForStorage; exports.ensureSchema = _chunkQHVID3V2cjs.ensureSchema; exports.getSchemaVersion = _chunkQHVID3V2cjs.getSchemaVersion; exports.isNonRetryableError = _chunkQHVID3V2cjs.isNonRetryableError; exports.isValidTimeZoneId = _chunkQHVID3V2cjs.isValidTimeZoneId; exports.measurePushPayload = _chunkQHVID3V2cjs.measurePushPayload; exports.nextFutureOccurrence = _chunkQHVID3V2cjs.nextFutureOccurrence; exports.planNextOccurrence = _chunkQHVID3V2cjs.planNextOccurrence; exports.readRequestBody = _chunkQHVID3V2cjs.readRequestBody; exports.runScheduledTick = _chunkQHVID3V2cjs.runScheduledTick; exports.runTask = _chunkQHVID3V2cjs.runTask; exports.summarizeErrorCause = _chunkQHVID3V2cjs.summarizeErrorCause;
|
package/dist/cloudflare.d.ts
CHANGED
|
@@ -6,4 +6,5 @@ export { runScheduledTick, runTask } from "./lib/run-tick.js";
|
|
|
6
6
|
export { getSchemaVersion, ensureSchema, SCHEMA_VERSION } from "./lib/schema-version.js";
|
|
7
7
|
export { summarizeErrorCause, NonRetryableError, isNonRetryableError } from "./lib/errors.js";
|
|
8
8
|
export { isValidTimeZoneId, advanceOccurrence, nextFutureOccurrence, planNextOccurrence } from "./lib/recurrence.js";
|
|
9
|
+
export { readRequestBody, DEFAULT_MAX_REQUEST_BODY_BYTES } from "./lib/request.js";
|
|
9
10
|
export { deriveUserEncryptionKey, decryptPayload, encryptForStorage, decryptFromStorage } from "./lib/encryption.js";
|
package/dist/cloudflare.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
DEFAULT_MAX_REQUEST_BODY_BYTES,
|
|
2
3
|
MAX_PUSH_PAYLOAD_BYTES,
|
|
3
4
|
NonRetryableError,
|
|
4
5
|
PUSH_ENVELOPE_RESERVED_BYTES,
|
|
@@ -21,12 +22,14 @@ import {
|
|
|
21
22
|
measurePushPayload,
|
|
22
23
|
nextFutureOccurrence,
|
|
23
24
|
planNextOccurrence,
|
|
25
|
+
readRequestBody,
|
|
24
26
|
runScheduledTick,
|
|
25
27
|
runTask,
|
|
26
28
|
summarizeErrorCause
|
|
27
|
-
} from "./chunk-
|
|
28
|
-
import "./chunk-
|
|
29
|
+
} from "./chunk-KOJQVOYS.mjs";
|
|
30
|
+
import "./chunk-GN44PST5.mjs";
|
|
29
31
|
export {
|
|
32
|
+
DEFAULT_MAX_REQUEST_BODY_BYTES,
|
|
30
33
|
MAX_PUSH_PAYLOAD_BYTES,
|
|
31
34
|
NonRetryableError,
|
|
32
35
|
PUSH_ENVELOPE_RESERVED_BYTES,
|
|
@@ -49,6 +52,7 @@ export {
|
|
|
49
52
|
measurePushPayload,
|
|
50
53
|
nextFutureOccurrence,
|
|
51
54
|
planNextOccurrence,
|
|
55
|
+
readRequestBody,
|
|
52
56
|
runScheduledTick,
|
|
53
57
|
runTask,
|
|
54
58
|
summarizeErrorCause
|
package/dist/index.cjs
CHANGED
|
@@ -67,8 +67,12 @@
|
|
|
67
67
|
|
|
68
68
|
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
var _chunkQHVID3V2cjs = require('./chunk-QHVID3V2.cjs');
|
|
75
|
+
require('./chunk-7NMQFTDJ.cjs');
|
|
72
76
|
|
|
73
77
|
// src/server/adapters/factory.js
|
|
74
78
|
async function createAdapter(config) {
|
|
@@ -84,11 +88,11 @@ async function createAdapter(config) {
|
|
|
84
88
|
}
|
|
85
89
|
switch (config.driver) {
|
|
86
90
|
case "neon": {
|
|
87
|
-
const { NeonAdapter } = await Promise.resolve().then(() => _interopRequireWildcard(require("./neon-
|
|
91
|
+
const { NeonAdapter } = await Promise.resolve().then(() => _interopRequireWildcard(require("./neon-KP2CPA57.cjs")));
|
|
88
92
|
return new NeonAdapter(config.connectionString);
|
|
89
93
|
}
|
|
90
94
|
case "pg": {
|
|
91
|
-
const { PgAdapter } = await Promise.resolve().then(() => _interopRequireWildcard(require("./pg-
|
|
95
|
+
const { PgAdapter } = await Promise.resolve().then(() => _interopRequireWildcard(require("./pg-RZPQGXR3.cjs")));
|
|
92
96
|
return new PgAdapter(config.connectionString);
|
|
93
97
|
}
|
|
94
98
|
default:
|
|
@@ -101,7 +105,7 @@ async function createAdapter(config) {
|
|
|
101
105
|
// src/server/handlers/init-tenant.js
|
|
102
106
|
function createInitTenantHandler(ctx) {
|
|
103
107
|
async function POST(headers, body) {
|
|
104
|
-
const initSecret =
|
|
108
|
+
const initSecret = _chunkQHVID3V2cjs.getHeader.call(void 0, headers, "x-init-secret");
|
|
105
109
|
if (ctx.tenant.initSecret && initSecret !== ctx.tenant.initSecret) {
|
|
106
110
|
return {
|
|
107
111
|
status: 401,
|
|
@@ -114,7 +118,7 @@ function createInitTenantHandler(ctx) {
|
|
|
114
118
|
}
|
|
115
119
|
};
|
|
116
120
|
}
|
|
117
|
-
const parsed =
|
|
121
|
+
const parsed = _chunkQHVID3V2cjs.parseJsonBody.call(void 0, body);
|
|
118
122
|
if (!parsed.ok) {
|
|
119
123
|
return {
|
|
120
124
|
status: 400,
|
|
@@ -128,7 +132,7 @@ function createInitTenantHandler(ctx) {
|
|
|
128
132
|
const tenantId = payload.tenantId || void 0;
|
|
129
133
|
const driver = payload.driver;
|
|
130
134
|
const databaseUrl = payload.databaseUrl || payload.connectionString;
|
|
131
|
-
if (tenantId && !
|
|
135
|
+
if (tenantId && !_chunkQHVID3V2cjs.isValidUUIDv4.call(void 0, tenantId)) {
|
|
132
136
|
return {
|
|
133
137
|
status: 400,
|
|
134
138
|
body: {
|
|
@@ -248,7 +252,7 @@ function createSendNotificationsHandler(ctx) {
|
|
|
248
252
|
}
|
|
249
253
|
};
|
|
250
254
|
}
|
|
251
|
-
const data = await
|
|
255
|
+
const data = await _chunkQHVID3V2cjs.runScheduledTick.call(void 0, { ...ctx, db, masterKey });
|
|
252
256
|
return { status: 200, body: { success: true, data } };
|
|
253
257
|
}
|
|
254
258
|
return { POST };
|
|
@@ -270,16 +274,16 @@ function encryptConfig(config, kekBuffer) {
|
|
|
270
274
|
const plaintext = Buffer.from(JSON.stringify(config), "utf8");
|
|
271
275
|
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
272
276
|
const authTag = cipher.getAuthTag();
|
|
273
|
-
return `v1.${
|
|
277
|
+
return `v1.${_chunkQHVID3V2cjs.bytesToBase64Url.call(void 0, iv)}.${_chunkQHVID3V2cjs.bytesToBase64Url.call(void 0, authTag)}.${_chunkQHVID3V2cjs.bytesToBase64Url.call(void 0, ciphertext)}`;
|
|
274
278
|
}
|
|
275
279
|
function decryptConfig(encrypted, kekBuffer) {
|
|
276
280
|
const parts = String(encrypted || "").split(".");
|
|
277
281
|
if (parts.length !== 4 || parts[0] !== "v1") {
|
|
278
282
|
throw new Error("INVALID_TENANT_CONFIG");
|
|
279
283
|
}
|
|
280
|
-
const iv =
|
|
281
|
-
const authTag =
|
|
282
|
-
const ciphertext =
|
|
284
|
+
const iv = _chunkQHVID3V2cjs.base64UrlToBytes.call(void 0, parts[1]);
|
|
285
|
+
const authTag = _chunkQHVID3V2cjs.base64UrlToBytes.call(void 0, parts[2]);
|
|
286
|
+
const ciphertext = _chunkQHVID3V2cjs.base64UrlToBytes.call(void 0, parts[3]);
|
|
283
287
|
const decipher = _crypto.createDecipheriv.call(void 0, "aes-256-gcm", kekBuffer, iv);
|
|
284
288
|
decipher.setAuthTag(authTag);
|
|
285
289
|
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
|
|
@@ -347,7 +351,7 @@ function createTenantBlobStore(options) {
|
|
|
347
351
|
// src/server/tenant/token.js
|
|
348
352
|
|
|
349
353
|
function sign(input, secret) {
|
|
350
|
-
return
|
|
354
|
+
return _chunkQHVID3V2cjs.bytesToBase64Url.call(void 0, _crypto.createHmac.call(void 0, "sha256", secret).update(input).digest());
|
|
351
355
|
}
|
|
352
356
|
function nowEpochSeconds() {
|
|
353
357
|
return Math.floor(Date.now() / 1e3);
|
|
@@ -363,8 +367,8 @@ function createTenantToken(params, secret) {
|
|
|
363
367
|
v: 1
|
|
364
368
|
};
|
|
365
369
|
const header = { alg: "HS256", typ: "JWT" };
|
|
366
|
-
const encodedHeader =
|
|
367
|
-
const encodedPayload =
|
|
370
|
+
const encodedHeader = _chunkQHVID3V2cjs.bytesToBase64Url.call(void 0, _chunkQHVID3V2cjs.utf8.call(void 0, JSON.stringify(header)));
|
|
371
|
+
const encodedPayload = _chunkQHVID3V2cjs.bytesToBase64Url.call(void 0, _chunkQHVID3V2cjs.utf8.call(void 0, JSON.stringify(payload)));
|
|
368
372
|
const signingInput = `${encodedHeader}.${encodedPayload}`;
|
|
369
373
|
const signature = sign(signingInput, secret);
|
|
370
374
|
return `${signingInput}.${signature}`;
|
|
@@ -383,17 +387,17 @@ function verifyTenantToken(token, secret, options = {}) {
|
|
|
383
387
|
let receivedBytes;
|
|
384
388
|
let expectedBytes;
|
|
385
389
|
try {
|
|
386
|
-
receivedBytes =
|
|
387
|
-
expectedBytes =
|
|
390
|
+
receivedBytes = _chunkQHVID3V2cjs.base64UrlToBytes.call(void 0, receivedSignature);
|
|
391
|
+
expectedBytes = _chunkQHVID3V2cjs.base64UrlToBytes.call(void 0, expectedSignature);
|
|
388
392
|
} catch (e) {
|
|
389
393
|
throw new Error("INVALID_TENANT_AUTH");
|
|
390
394
|
}
|
|
391
|
-
if (!
|
|
395
|
+
if (!_chunkQHVID3V2cjs.timingSafeEqualBytes.call(void 0, receivedBytes, expectedBytes)) {
|
|
392
396
|
throw new Error("INVALID_TENANT_AUTH");
|
|
393
397
|
}
|
|
394
398
|
let payload;
|
|
395
399
|
try {
|
|
396
|
-
payload = JSON.parse(
|
|
400
|
+
payload = JSON.parse(_chunkQHVID3V2cjs.utf8Decode.call(void 0, _chunkQHVID3V2cjs.base64UrlToBytes.call(void 0, encodedPayload)));
|
|
397
401
|
} catch (e2) {
|
|
398
402
|
throw new Error("INVALID_TENANT_AUTH");
|
|
399
403
|
}
|
|
@@ -605,6 +609,10 @@ async function createReiServer(config) {
|
|
|
605
609
|
privateKey: vapid.privateKey || ""
|
|
606
610
|
},
|
|
607
611
|
webpush: webpushModule,
|
|
612
|
+
// 分片传输的限额(与 installReiSW 的 multipart 同一份)。instant 消息在
|
|
613
|
+
// schedule-message 里就地投递、定时消息走 send-notifications 的 tick,两条路
|
|
614
|
+
// 都从这个 ctx 展开,所以配一次两边都认。
|
|
615
|
+
multipart: config.multipart || null,
|
|
608
616
|
tenant: {
|
|
609
617
|
initSecret
|
|
610
618
|
},
|
|
@@ -613,15 +621,15 @@ async function createReiServer(config) {
|
|
|
613
621
|
return {
|
|
614
622
|
handlers: {
|
|
615
623
|
initTenant: createInitTenantHandler(ctx),
|
|
616
|
-
getUserKey:
|
|
617
|
-
scheduleMessage:
|
|
624
|
+
getUserKey: _chunkQHVID3V2cjs.createGetUserKeyHandler.call(void 0, ctx),
|
|
625
|
+
scheduleMessage: _chunkQHVID3V2cjs.createScheduleMessageHandler.call(void 0, ctx),
|
|
618
626
|
sendNotifications: createSendNotificationsHandler(ctx),
|
|
619
|
-
updateMessage:
|
|
620
|
-
cancelMessage:
|
|
621
|
-
messages:
|
|
622
|
-
getMessage:
|
|
623
|
-
pushSubscription:
|
|
624
|
-
llmCredentials:
|
|
627
|
+
updateMessage: _chunkQHVID3V2cjs.createUpdateMessageHandler.call(void 0, ctx),
|
|
628
|
+
cancelMessage: _chunkQHVID3V2cjs.createCancelMessageHandler.call(void 0, ctx),
|
|
629
|
+
messages: _chunkQHVID3V2cjs.createMessagesHandler.call(void 0, ctx),
|
|
630
|
+
getMessage: _chunkQHVID3V2cjs.createGetMessageHandler.call(void 0, ctx),
|
|
631
|
+
pushSubscription: _chunkQHVID3V2cjs.createPushSubscriptionHandler.call(void 0, ctx),
|
|
632
|
+
llmCredentials: _chunkQHVID3V2cjs.createLlmCredentialsHandler.call(void 0, ctx)
|
|
625
633
|
}
|
|
626
634
|
};
|
|
627
635
|
}
|
|
@@ -683,4 +691,8 @@ async function createReiServer(config) {
|
|
|
683
691
|
|
|
684
692
|
|
|
685
693
|
|
|
686
|
-
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
exports.CORS_ALLOW_HEADERS = _chunkQHVID3V2cjs.CORS_ALLOW_HEADERS; exports.CORS_ALLOW_METHODS = _chunkQHVID3V2cjs.CORS_ALLOW_METHODS; exports.CRED_ID_MAX_LENGTH = _chunkQHVID3V2cjs.CRED_ID_MAX_LENGTH; exports.CRED_PUT_BATCH_MAX = _chunkQHVID3V2cjs.CRED_PUT_BATCH_MAX; exports.CRED_REFS_MAX_ENTRIES = _chunkQHVID3V2cjs.CRED_REFS_MAX_ENTRIES; exports.CRED_ROWS_PER_USER_MAX = _chunkQHVID3V2cjs.CRED_ROWS_PER_USER_MAX; exports.DEFAULT_CLAIM_LEASE_MS = _chunkQHVID3V2cjs.DEFAULT_CLAIM_LEASE_MS; exports.DEFAULT_HEARTBEAT_LEASE_TTL_MS = _chunkQHVID3V2cjs.DEFAULT_HEARTBEAT_LEASE_TTL_MS; exports.DEFAULT_LEASE_HEARTBEAT_MS = _chunkQHVID3V2cjs.DEFAULT_LEASE_HEARTBEAT_MS; exports.DEFAULT_MAX_REQUEST_BODY_BYTES = _chunkQHVID3V2cjs.DEFAULT_MAX_REQUEST_BODY_BYTES; exports.DEFAULT_MAX_SCHEDULED_TASKS_PER_FIRE = _chunkQHVID3V2cjs.DEFAULT_MAX_SCHEDULED_TASKS_PER_FIRE; exports.DEFAULT_MAX_TOOL_ITERATIONS = _chunkQHVID3V2cjs.DEFAULT_MAX_TOOL_ITERATIONS; exports.DEFAULT_TOTAL_TIMEOUT_MS = _chunkQHVID3V2cjs.DEFAULT_TOTAL_TIMEOUT_MS; exports.DeploymentConfigError = _chunkQHVID3V2cjs.DeploymentConfigError; exports.MAX_PUSH_PAYLOAD_BYTES = _chunkQHVID3V2cjs.MAX_PUSH_PAYLOAD_BYTES; exports.MAX_TASK_PAYLOAD_BYTES = _chunkQHVID3V2cjs.MAX_TASK_PAYLOAD_BYTES; exports.MIN_SCHEDULE_LEAD_MS = _chunkQHVID3V2cjs.MIN_SCHEDULE_LEAD_MS; exports.NonRetryableError = _chunkQHVID3V2cjs.NonRetryableError; exports.PUSH_ENVELOPE_RESERVED_BYTES = _chunkQHVID3V2cjs.PUSH_ENVELOPE_RESERVED_BYTES; exports.SCHEMA_VERSION = _chunkQHVID3V2cjs.SCHEMA_VERSION; exports.WEB_PUSH_ENCRYPTION_OVERHEAD_BYTES = _chunkQHVID3V2cjs.WEB_PUSH_ENCRYPTION_OVERHEAD_BYTES; exports.WEB_PUSH_MAX_BODY_BYTES = _chunkQHVID3V2cjs.WEB_PUSH_MAX_BODY_BYTES; exports.advanceOccurrence = _chunkQHVID3V2cjs.advanceOccurrence; exports.createAdapter = createAdapter; exports.createD1Adapter = _chunkQHVID3V2cjs.createD1Adapter; exports.createReiServer = createReiServer; exports.createSingleUserCloudflareWorker = _chunkQHVID3V2cjs.createSingleUserCloudflareWorker; exports.createSingleUserServer = _chunkQHVID3V2cjs.createSingleUserServer; exports.createTenantToken = createTenantToken; exports.createWebCryptoWebPush = _chunkQHVID3V2cjs.createWebCryptoWebPush; exports.decryptFromStorage = _chunkQHVID3V2cjs.decryptFromStorage; exports.decryptPayload = _chunkQHVID3V2cjs.decryptPayload; exports.deriveUserEncryptionKey = _chunkQHVID3V2cjs.deriveUserEncryptionKey; exports.encryptForStorage = _chunkQHVID3V2cjs.encryptForStorage; exports.ensureSchema = _chunkQHVID3V2cjs.ensureSchema; exports.getSchemaVersion = _chunkQHVID3V2cjs.getSchemaVersion; exports.hasChatCredRef = _chunkQHVID3V2cjs.hasChatCredRef; exports.isNonRetryableError = _chunkQHVID3V2cjs.isNonRetryableError; exports.isValidCredId = _chunkQHVID3V2cjs.isValidCredId; exports.isValidISO8601 = _chunkQHVID3V2cjs.isValidISO8601; exports.isValidTimeZoneId = _chunkQHVID3V2cjs.isValidTimeZoneId; exports.isValidUUID = _chunkQHVID3V2cjs.isValidUUID; exports.isValidUUIDv4 = _chunkQHVID3V2cjs.isValidUUIDv4; exports.isValidUrl = _chunkQHVID3V2cjs.isValidUrl; exports.measurePushPayload = _chunkQHVID3V2cjs.measurePushPayload; exports.nextFutureOccurrence = _chunkQHVID3V2cjs.nextFutureOccurrence; exports.planNextOccurrence = _chunkQHVID3V2cjs.planNextOccurrence; exports.readRequestBody = _chunkQHVID3V2cjs.readRequestBody; exports.resolveLlmCredential = _chunkQHVID3V2cjs.resolveLlmCredential; exports.runScheduledTick = _chunkQHVID3V2cjs.runScheduledTick; exports.runTask = _chunkQHVID3V2cjs.runTask; exports.sanitizeErrorSummary = _chunkQHVID3V2cjs.sanitizeErrorSummary; exports.summarizeErrorCause = _chunkQHVID3V2cjs.summarizeErrorCause; exports.supportsLlmCredentialsStore = _chunkQHVID3V2cjs.supportsLlmCredentialsStore; exports.validateAvatarUrl = _chunkQHVID3V2cjs.validateAvatarUrl; exports.validateCredRefs = _chunkQHVID3V2cjs.validateCredRefs; exports.validateCredValue = _chunkQHVID3V2cjs.validateCredValue; exports.validateLlmMessagesArray = _chunkQHVID3V2cjs.validateLlmMessagesArray; exports.validateScheduleMessagePayload = _chunkQHVID3V2cjs.validateScheduleMessagePayload; exports.validateSplitPattern = _chunkQHVID3V2cjs.validateSplitPattern; exports.verifyTenantToken = verifyTenantToken;
|
package/dist/index.d.cts
CHANGED
|
@@ -18,6 +18,11 @@
|
|
|
18
18
|
* @typedef {Object} ReiServerConfig
|
|
19
19
|
* @property {VapidConfig} [vapid] - VAPID keys for Web Push.
|
|
20
20
|
* @property {TenantServerConfig} tenant - Tenant config & auth settings.
|
|
21
|
+
* @property {{ maxChunkBytes?: number, maxChunks?: number, maxTotalBytes?: number, ttlMs?: number }} [multipart]
|
|
22
|
+
* 分片传输的限额,跟传给 `installReiSW` 的那一份保持一致(同名同键,原样传过来
|
|
23
|
+
* 即可)。一条 push 装不下的思考过程要切片发,切多大、最多几片、重组窗口多长由
|
|
24
|
+
* 接收端说了算——发送端不知道这份配置的话,切出来的分片到了那边会被逐片拒收,
|
|
25
|
+
* 或者整批没能在重组窗口内发完,一条也拼不回来。不配 = 两边都用默认值。
|
|
21
26
|
*/
|
|
22
27
|
/**
|
|
23
28
|
* @typedef {Object} ReiHandlers
|
|
@@ -98,6 +103,18 @@ export type ReiServerConfig = {
|
|
|
98
103
|
* - Tenant config & auth settings.
|
|
99
104
|
*/
|
|
100
105
|
tenant: TenantServerConfig;
|
|
106
|
+
/**
|
|
107
|
+
* 分片传输的限额,跟传给 `installReiSW` 的那一份保持一致(同名同键,原样传过来
|
|
108
|
+
* 即可)。一条 push 装不下的思考过程要切片发,切多大、最多几片、重组窗口多长由
|
|
109
|
+
* 接收端说了算——发送端不知道这份配置的话,切出来的分片到了那边会被逐片拒收,
|
|
110
|
+
* 或者整批没能在重组窗口内发完,一条也拼不回来。不配 = 两边都用默认值。
|
|
111
|
+
*/
|
|
112
|
+
multipart?: {
|
|
113
|
+
maxChunkBytes?: number;
|
|
114
|
+
maxChunks?: number;
|
|
115
|
+
maxTotalBytes?: number;
|
|
116
|
+
ttlMs?: number;
|
|
117
|
+
};
|
|
101
118
|
};
|
|
102
119
|
export type ReiHandlers = {
|
|
103
120
|
initTenant: {
|
|
@@ -142,13 +159,14 @@ export type ReiServer = {
|
|
|
142
159
|
handlers: ReiHandlers;
|
|
143
160
|
};
|
|
144
161
|
export { runScheduledTick, runTask, DEFAULT_CLAIM_LEASE_MS, DEFAULT_LEASE_HEARTBEAT_MS, DEFAULT_HEARTBEAT_LEASE_TTL_MS, sanitizeErrorSummary } from "./lib/run-tick.js";
|
|
145
|
-
export { NonRetryableError, isNonRetryableError, summarizeErrorCause } from "./lib/errors.js";
|
|
162
|
+
export { NonRetryableError, DeploymentConfigError, isNonRetryableError, summarizeErrorCause } from "./lib/errors.js";
|
|
146
163
|
export { getSchemaVersion, ensureSchema, SCHEMA_VERSION } from "./lib/schema-version.js";
|
|
147
164
|
export { DEFAULT_MAX_TOOL_ITERATIONS, DEFAULT_TOTAL_TIMEOUT_MS, DEFAULT_MAX_SCHEDULED_TASKS_PER_FIRE, MIN_SCHEDULE_LEAD_MS } from "./lib/agentic-fire.js";
|
|
148
165
|
export { CORS_ALLOW_HEADERS, CORS_ALLOW_METHODS, createSingleUserCloudflareWorker } from "./cloudflare/single-user-worker.js";
|
|
149
166
|
export { createWebCryptoWebPush, measurePushPayload, MAX_PUSH_PAYLOAD_BYTES, PUSH_ENVELOPE_RESERVED_BYTES, WEB_PUSH_MAX_BODY_BYTES, WEB_PUSH_ENCRYPTION_OVERHEAD_BYTES } from "./lib/webpush-webcrypto.js";
|
|
150
167
|
export { deriveUserEncryptionKey, decryptPayload, encryptForStorage, decryptFromStorage } from "./lib/encryption.js";
|
|
151
|
-
export { validateScheduleMessagePayload, validateLlmMessagesArray, validateSplitPattern, validateAvatarUrl, isValidISO8601, isValidUrl, isValidUUID, isValidUUIDv4, isValidTimeZoneId } from "./lib/validation.js";
|
|
168
|
+
export { validateScheduleMessagePayload, validateLlmMessagesArray, validateSplitPattern, validateAvatarUrl, isValidISO8601, isValidUrl, isValidUUID, isValidUUIDv4, isValidTimeZoneId, MAX_TASK_PAYLOAD_BYTES } from "./lib/validation.js";
|
|
169
|
+
export { readRequestBody, DEFAULT_MAX_REQUEST_BODY_BYTES } from "./lib/request.js";
|
|
152
170
|
export { supportsLlmCredentialsStore, isValidCredId, validateCredRefs, validateCredValue, hasChatCredRef, resolveLlmCredential, CRED_ID_MAX_LENGTH, CRED_PUT_BATCH_MAX, CRED_ROWS_PER_USER_MAX, CRED_REFS_MAX_ENTRIES } from "./lib/llm-credentials-store.js";
|
|
153
171
|
export { advanceOccurrence, nextFutureOccurrence, planNextOccurrence } from "./lib/recurrence.js";
|
|
154
172
|
export { createTenantToken, verifyTenantToken } from "./tenant/token.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,11 @@
|
|
|
18
18
|
* @typedef {Object} ReiServerConfig
|
|
19
19
|
* @property {VapidConfig} [vapid] - VAPID keys for Web Push.
|
|
20
20
|
* @property {TenantServerConfig} tenant - Tenant config & auth settings.
|
|
21
|
+
* @property {{ maxChunkBytes?: number, maxChunks?: number, maxTotalBytes?: number, ttlMs?: number }} [multipart]
|
|
22
|
+
* 分片传输的限额,跟传给 `installReiSW` 的那一份保持一致(同名同键,原样传过来
|
|
23
|
+
* 即可)。一条 push 装不下的思考过程要切片发,切多大、最多几片、重组窗口多长由
|
|
24
|
+
* 接收端说了算——发送端不知道这份配置的话,切出来的分片到了那边会被逐片拒收,
|
|
25
|
+
* 或者整批没能在重组窗口内发完,一条也拼不回来。不配 = 两边都用默认值。
|
|
21
26
|
*/
|
|
22
27
|
/**
|
|
23
28
|
* @typedef {Object} ReiHandlers
|
|
@@ -98,6 +103,18 @@ export type ReiServerConfig = {
|
|
|
98
103
|
* - Tenant config & auth settings.
|
|
99
104
|
*/
|
|
100
105
|
tenant: TenantServerConfig;
|
|
106
|
+
/**
|
|
107
|
+
* 分片传输的限额,跟传给 `installReiSW` 的那一份保持一致(同名同键,原样传过来
|
|
108
|
+
* 即可)。一条 push 装不下的思考过程要切片发,切多大、最多几片、重组窗口多长由
|
|
109
|
+
* 接收端说了算——发送端不知道这份配置的话,切出来的分片到了那边会被逐片拒收,
|
|
110
|
+
* 或者整批没能在重组窗口内发完,一条也拼不回来。不配 = 两边都用默认值。
|
|
111
|
+
*/
|
|
112
|
+
multipart?: {
|
|
113
|
+
maxChunkBytes?: number;
|
|
114
|
+
maxChunks?: number;
|
|
115
|
+
maxTotalBytes?: number;
|
|
116
|
+
ttlMs?: number;
|
|
117
|
+
};
|
|
101
118
|
};
|
|
102
119
|
export type ReiHandlers = {
|
|
103
120
|
initTenant: {
|
|
@@ -142,13 +159,14 @@ export type ReiServer = {
|
|
|
142
159
|
handlers: ReiHandlers;
|
|
143
160
|
};
|
|
144
161
|
export { runScheduledTick, runTask, DEFAULT_CLAIM_LEASE_MS, DEFAULT_LEASE_HEARTBEAT_MS, DEFAULT_HEARTBEAT_LEASE_TTL_MS, sanitizeErrorSummary } from "./lib/run-tick.js";
|
|
145
|
-
export { NonRetryableError, isNonRetryableError, summarizeErrorCause } from "./lib/errors.js";
|
|
162
|
+
export { NonRetryableError, DeploymentConfigError, isNonRetryableError, summarizeErrorCause } from "./lib/errors.js";
|
|
146
163
|
export { getSchemaVersion, ensureSchema, SCHEMA_VERSION } from "./lib/schema-version.js";
|
|
147
164
|
export { DEFAULT_MAX_TOOL_ITERATIONS, DEFAULT_TOTAL_TIMEOUT_MS, DEFAULT_MAX_SCHEDULED_TASKS_PER_FIRE, MIN_SCHEDULE_LEAD_MS } from "./lib/agentic-fire.js";
|
|
148
165
|
export { CORS_ALLOW_HEADERS, CORS_ALLOW_METHODS, createSingleUserCloudflareWorker } from "./cloudflare/single-user-worker.js";
|
|
149
166
|
export { createWebCryptoWebPush, measurePushPayload, MAX_PUSH_PAYLOAD_BYTES, PUSH_ENVELOPE_RESERVED_BYTES, WEB_PUSH_MAX_BODY_BYTES, WEB_PUSH_ENCRYPTION_OVERHEAD_BYTES } from "./lib/webpush-webcrypto.js";
|
|
150
167
|
export { deriveUserEncryptionKey, decryptPayload, encryptForStorage, decryptFromStorage } from "./lib/encryption.js";
|
|
151
|
-
export { validateScheduleMessagePayload, validateLlmMessagesArray, validateSplitPattern, validateAvatarUrl, isValidISO8601, isValidUrl, isValidUUID, isValidUUIDv4, isValidTimeZoneId } from "./lib/validation.js";
|
|
168
|
+
export { validateScheduleMessagePayload, validateLlmMessagesArray, validateSplitPattern, validateAvatarUrl, isValidISO8601, isValidUrl, isValidUUID, isValidUUIDv4, isValidTimeZoneId, MAX_TASK_PAYLOAD_BYTES } from "./lib/validation.js";
|
|
169
|
+
export { readRequestBody, DEFAULT_MAX_REQUEST_BODY_BYTES } from "./lib/request.js";
|
|
152
170
|
export { supportsLlmCredentialsStore, isValidCredId, validateCredRefs, validateCredValue, hasChatCredRef, resolveLlmCredential, CRED_ID_MAX_LENGTH, CRED_PUT_BATCH_MAX, CRED_ROWS_PER_USER_MAX, CRED_REFS_MAX_ENTRIES } from "./lib/llm-credentials-store.js";
|
|
153
171
|
export { advanceOccurrence, nextFutureOccurrence, planNextOccurrence } from "./lib/recurrence.js";
|
|
154
172
|
export { createTenantToken, verifyTenantToken } from "./tenant/token.js";
|
package/dist/index.mjs
CHANGED
|
@@ -8,10 +8,13 @@ import {
|
|
|
8
8
|
DEFAULT_CLAIM_LEASE_MS,
|
|
9
9
|
DEFAULT_HEARTBEAT_LEASE_TTL_MS,
|
|
10
10
|
DEFAULT_LEASE_HEARTBEAT_MS,
|
|
11
|
+
DEFAULT_MAX_REQUEST_BODY_BYTES,
|
|
11
12
|
DEFAULT_MAX_SCHEDULED_TASKS_PER_FIRE,
|
|
12
13
|
DEFAULT_MAX_TOOL_ITERATIONS,
|
|
13
14
|
DEFAULT_TOTAL_TIMEOUT_MS,
|
|
15
|
+
DeploymentConfigError,
|
|
14
16
|
MAX_PUSH_PAYLOAD_BYTES,
|
|
17
|
+
MAX_TASK_PAYLOAD_BYTES,
|
|
15
18
|
MIN_SCHEDULE_LEAD_MS,
|
|
16
19
|
NonRetryableError,
|
|
17
20
|
PUSH_ENVELOPE_RESERVED_BYTES,
|
|
@@ -52,6 +55,7 @@ import {
|
|
|
52
55
|
nextFutureOccurrence,
|
|
53
56
|
parseJsonBody,
|
|
54
57
|
planNextOccurrence,
|
|
58
|
+
readRequestBody,
|
|
55
59
|
resolveLlmCredential,
|
|
56
60
|
runScheduledTick,
|
|
57
61
|
runTask,
|
|
@@ -67,8 +71,8 @@ import {
|
|
|
67
71
|
validateLlmMessagesArray,
|
|
68
72
|
validateScheduleMessagePayload,
|
|
69
73
|
validateSplitPattern
|
|
70
|
-
} from "./chunk-
|
|
71
|
-
import "./chunk-
|
|
74
|
+
} from "./chunk-KOJQVOYS.mjs";
|
|
75
|
+
import "./chunk-GN44PST5.mjs";
|
|
72
76
|
|
|
73
77
|
// src/server/adapters/factory.js
|
|
74
78
|
async function createAdapter(config) {
|
|
@@ -84,11 +88,11 @@ async function createAdapter(config) {
|
|
|
84
88
|
}
|
|
85
89
|
switch (config.driver) {
|
|
86
90
|
case "neon": {
|
|
87
|
-
const { NeonAdapter } = await import("./neon-
|
|
91
|
+
const { NeonAdapter } = await import("./neon-ZIMHALYI.mjs");
|
|
88
92
|
return new NeonAdapter(config.connectionString);
|
|
89
93
|
}
|
|
90
94
|
case "pg": {
|
|
91
|
-
const { PgAdapter } = await import("./pg-
|
|
95
|
+
const { PgAdapter } = await import("./pg-QGC2XHUT.mjs");
|
|
92
96
|
return new PgAdapter(config.connectionString);
|
|
93
97
|
}
|
|
94
98
|
default:
|
|
@@ -605,6 +609,10 @@ async function createReiServer(config) {
|
|
|
605
609
|
privateKey: vapid.privateKey || ""
|
|
606
610
|
},
|
|
607
611
|
webpush: webpushModule,
|
|
612
|
+
// 分片传输的限额(与 installReiSW 的 multipart 同一份)。instant 消息在
|
|
613
|
+
// schedule-message 里就地投递、定时消息走 send-notifications 的 tick,两条路
|
|
614
|
+
// 都从这个 ctx 展开,所以配一次两边都认。
|
|
615
|
+
multipart: config.multipart || null,
|
|
608
616
|
tenant: {
|
|
609
617
|
initSecret
|
|
610
618
|
},
|
|
@@ -635,10 +643,13 @@ export {
|
|
|
635
643
|
DEFAULT_CLAIM_LEASE_MS,
|
|
636
644
|
DEFAULT_HEARTBEAT_LEASE_TTL_MS,
|
|
637
645
|
DEFAULT_LEASE_HEARTBEAT_MS,
|
|
646
|
+
DEFAULT_MAX_REQUEST_BODY_BYTES,
|
|
638
647
|
DEFAULT_MAX_SCHEDULED_TASKS_PER_FIRE,
|
|
639
648
|
DEFAULT_MAX_TOOL_ITERATIONS,
|
|
640
649
|
DEFAULT_TOTAL_TIMEOUT_MS,
|
|
650
|
+
DeploymentConfigError,
|
|
641
651
|
MAX_PUSH_PAYLOAD_BYTES,
|
|
652
|
+
MAX_TASK_PAYLOAD_BYTES,
|
|
642
653
|
MIN_SCHEDULE_LEAD_MS,
|
|
643
654
|
NonRetryableError,
|
|
644
655
|
PUSH_ENVELOPE_RESERVED_BYTES,
|
|
@@ -670,6 +681,7 @@ export {
|
|
|
670
681
|
measurePushPayload,
|
|
671
682
|
nextFutureOccurrence,
|
|
672
683
|
planNextOccurrence,
|
|
684
|
+
readRequestBody,
|
|
673
685
|
resolveLlmCredential,
|
|
674
686
|
runScheduledTick,
|
|
675
687
|
runTask,
|
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
/** value 的 UTF-8 字节数——各处限额判断用的都是这个口径。 */
|
|
2
2
|
export function stateValueBytes(value: any): number;
|
|
3
|
+
/**
|
|
4
|
+
* 把 `clientStateTtl` 配置(`{ 命名空间: 天数 }`)算成清理指令。
|
|
5
|
+
*
|
|
6
|
+
* 一个命名空间出两条:它自己,加上它的切片命名空间(大值分块存在那儿,见
|
|
7
|
+
* lib/state-chunks.js)。两边共用同一个截止时刻——同一次写入的根行和切片行
|
|
8
|
+
* `updated_at` 相同,所以要么一起留、要么一起走,不会留下半截数据。
|
|
9
|
+
*
|
|
10
|
+
* 天数不是正数的条目跳过并告警(每个键只说一次):配错了就该看得见,但不能
|
|
11
|
+
* 让 cron 每分钟刷一条。
|
|
12
|
+
*
|
|
13
|
+
* @param {Record<string, number>|null|undefined} ttl - `{ 命名空间: 天数 }`;天数可带小数
|
|
14
|
+
* @param {number} now - 当前时刻(epoch 毫秒)
|
|
15
|
+
* @returns {Array<{ namespace: string, updatedBefore: number }>}
|
|
16
|
+
* `updatedBefore` 是 epoch 毫秒:这个命名空间下 `updated_at` 早于它的条目该清掉。
|
|
17
|
+
*/
|
|
18
|
+
export function planClientStateCleanup(ttl: Record<string, number> | null | undefined, now: number): Array<{
|
|
19
|
+
namespace: string;
|
|
20
|
+
updatedBefore: number;
|
|
21
|
+
}>;
|
|
3
22
|
/**
|
|
4
23
|
* 把逻辑条目写进 client_state。条目要么是覆盖写(`value` 是字符串),要么是
|
|
5
24
|
* 删除(`value` 为 `null`):
|
package/dist/lib/errors.d.ts
CHANGED
|
@@ -6,12 +6,96 @@
|
|
|
6
6
|
* @returns {boolean}
|
|
7
7
|
*/
|
|
8
8
|
export function isNonRetryableError(error: unknown): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* 把一个已经构造好的错误标成确定性失败(就地改,原样返回),顺带补一个稳定
|
|
11
|
+
* 的 `code`(错误自己带了 code 就不覆盖)。
|
|
12
|
+
*
|
|
13
|
+
* 用在错误由别处构造、又想保住它原本类型的时候——比如契约校验抛的
|
|
14
|
+
* `TypeError`:宿主按 `instanceof TypeError` 分流的代码不该因为库多标了一个
|
|
15
|
+
* 字段就走岔。自己现造错误的地方直接用 {@link NonRetryableError} 更直白。
|
|
16
|
+
*
|
|
17
|
+
* @template T
|
|
18
|
+
* @param {T} error
|
|
19
|
+
* @param {string} [code]
|
|
20
|
+
* @returns {T}
|
|
21
|
+
*/
|
|
22
|
+
export function markPermanent<T>(error: T, code?: string): T;
|
|
23
|
+
/**
|
|
24
|
+
* 这个错误是不是「投递期间任务被取消/顶替」。
|
|
25
|
+
*
|
|
26
|
+
* @param {unknown} error
|
|
27
|
+
* @returns {boolean}
|
|
28
|
+
*/
|
|
29
|
+
export function isTaskCancelledError(error: unknown): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* 这次投递失败要不要判成永久性的(不再重试)。四个来源:
|
|
32
|
+
* - 已知的永久性错误码(见 {@link PERMANENT_ERROR_CODES});
|
|
33
|
+
* - hook 侧抛出的 NonRetryableError(`permanent`,见 {@link NonRetryableError})——
|
|
34
|
+
* fire_pack 缺失、解析失败这类重试必然同败的错,隔两分钟再试三次只是让用户
|
|
35
|
+
* 多白等十二分钟,还把情绪评估之类的计费重跑三遍;
|
|
36
|
+
* - 推送服务判了这条订阅的死刑(见 {@link TERMINAL_PUSH_STATUSES});
|
|
37
|
+
* - 推送服务说这条 payload 太大(见 {@link PUSH_PAYLOAD_TOO_LARGE_STATUS})。
|
|
38
|
+
*
|
|
39
|
+
* @param {{ permanent?: unknown, errorCode?: unknown, pushStatus?: unknown }} failure
|
|
40
|
+
* @returns {boolean}
|
|
41
|
+
*/
|
|
42
|
+
export function isPermanentDeliveryFailure(failure: {
|
|
43
|
+
permanent?: unknown;
|
|
44
|
+
errorCode?: unknown;
|
|
45
|
+
pushStatus?: unknown;
|
|
46
|
+
}): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* 发一条 push,失败时自动标上「这是发 push 那一步抛的」。
|
|
49
|
+
*
|
|
50
|
+
* 发 push 的地方一律走这里,别各自写 `try { send } catch { throw
|
|
51
|
+
* tagPushStatusCode(e) }`:漏标一处,那条路上的 410 就读不出状态码,一条早就
|
|
52
|
+
* 失效的订阅会被当成普通失败,在退避阶梯上把 LLM 重跑三轮。忘了标是没有任何
|
|
53
|
+
* 提示的。
|
|
54
|
+
*
|
|
55
|
+
* @param {{ sendNotification: (subscription: any, payload: string) => Promise<any> }} webpush
|
|
56
|
+
* @param {any} subscription
|
|
57
|
+
* @param {string} payloadJson
|
|
58
|
+
* @returns {Promise<any>}
|
|
59
|
+
*/
|
|
60
|
+
export function sendTaggedPush(webpush: {
|
|
61
|
+
sendNotification: (subscription: any, payload: string) => Promise<any>;
|
|
62
|
+
}, subscription: any, payloadJson: string): Promise<any>;
|
|
63
|
+
/**
|
|
64
|
+
* 读推送服务回的状态码。没被 {@link tagPushStatusCode} 标过 → null。
|
|
65
|
+
*
|
|
66
|
+
* @param {unknown} error
|
|
67
|
+
* @returns {number|null}
|
|
68
|
+
*/
|
|
69
|
+
export function readPushStatusCode(error: unknown): number | null;
|
|
70
|
+
/**
|
|
71
|
+
* lastError 里的机读标注:`errorCode` 是底层错误的稳定 code(如
|
|
72
|
+
* `PUSH_PAYLOAD_TOO_LARGE`),`pushStatus` 是推送服务回的 HTTP 状态码。两个都
|
|
73
|
+
* 没有 → undefined,不往记录里塞空字段。
|
|
74
|
+
*
|
|
75
|
+
* reason 那句是给用户看的人话、措辞随时会变,判断「该让用户重建订阅还是裁短
|
|
76
|
+
* 内容」得读这两个字段。定时任务(run-tick)与 instant 任务
|
|
77
|
+
* (processMessagesByUuid)共用这一份,两条路记下来的形状一致。
|
|
78
|
+
*
|
|
79
|
+
* code 是标识符不是人话,不用脱敏,但也别让一个来路不明的超长 code 撑大明文
|
|
80
|
+
* 列——截到 64 字符,够放所有约定过的码。
|
|
81
|
+
*
|
|
82
|
+
* @param {string|null|undefined} errorCode
|
|
83
|
+
* @param {number|null|undefined} pushStatus
|
|
84
|
+
* @returns {{ errorCode?: string, pushStatus?: number }|undefined}
|
|
85
|
+
*/
|
|
86
|
+
export function buildErrorExtra(errorCode: string | null | undefined, pushStatus: number | null | undefined): {
|
|
87
|
+
errorCode?: string;
|
|
88
|
+
pushStatus?: number;
|
|
89
|
+
} | undefined;
|
|
9
90
|
/**
|
|
10
91
|
* 把错误原因脱敏成能明文落库(任务行 last_error 列)的摘要。
|
|
11
92
|
*
|
|
12
93
|
* 任务内容一律密文落库,last_error 是唯一一列明文的「为什么没发出去」——
|
|
13
94
|
* 错误消息偶尔会回显请求细节(上游 API 的报错带 URL、header 片段),所以
|
|
14
|
-
* 长得像凭据的 token
|
|
95
|
+
* 长得像凭据的 token 一律遮掉,再截断。
|
|
96
|
+
*
|
|
97
|
+
* 遮什么、怎么遮由 @rei-standard/amsg-shared 的 `redactCredentials` 说了算,
|
|
98
|
+
* 这里只负责压平空白和截断。
|
|
15
99
|
*
|
|
16
100
|
* @param {unknown} reason
|
|
17
101
|
* @returns {string}
|
|
@@ -21,7 +105,10 @@ export function sanitizeErrorSummary(reason: unknown): string;
|
|
|
21
105
|
* @typedef {Object} ErrorCause
|
|
22
106
|
* @property {'config'|'request'|'tick'} stage - 在哪一段炸的
|
|
23
107
|
* @property {string} name - 错误类型(`error.name`,认不出来时是 'Error')
|
|
24
|
-
* @property {string} message -
|
|
108
|
+
* @property {string} [message] - 脱敏后的错误消息。降级 500(配置都没建起来那条
|
|
109
|
+
* 路)回给跨域调用方时不带这个字段——那条路的 CORS 头是回显来访 Origin 的,任
|
|
110
|
+
* 意第三方页面都能读,而构建期异常原文里常有 binding 名、内网域名、环境变量
|
|
111
|
+
* 名。同源 / 无 Origin 的请求照旧带全文,`wrangler tail` 里也一直有。
|
|
25
112
|
* @property {string} [code] - 错误自带的 `code` 字符串(有才带)
|
|
26
113
|
*/
|
|
27
114
|
/**
|
|
@@ -42,9 +129,6 @@ export function sanitizeErrorSummary(reason: unknown): string;
|
|
|
42
129
|
* @returns {ErrorCause}
|
|
43
130
|
*/
|
|
44
131
|
export function summarizeErrorCause(error: unknown, stage: "config" | "request" | "tick"): ErrorCause;
|
|
45
|
-
/**
|
|
46
|
-
* 错误类型:宿主 hook 与库内部共用的失败语义标注。
|
|
47
|
-
*/
|
|
48
132
|
/**
|
|
49
133
|
* 确定性失败——重试必然同败,别再排退避阶梯。
|
|
50
134
|
*
|
|
@@ -73,6 +157,41 @@ export class NonRetryableError extends Error {
|
|
|
73
157
|
permanent: boolean;
|
|
74
158
|
code: string;
|
|
75
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* 部署级的配置 / 适配器能力错误——坏的不是这条任务,是这个部署。
|
|
162
|
+
*
|
|
163
|
+
* 典型场景:`hooks.onBeforeFire` 配了但 `onLLMOutput` 忘了配、`executeToolCalls`
|
|
164
|
+
* 没配、自定义适配器缺 `createTask` / `deleteTaskByUuid` / `upsertClientState`。
|
|
165
|
+
* 这类错误重试确实好不了,但**不能**判终态:同一个坏部署下每条到点的任务都会
|
|
166
|
+
* 撞同一个错,判终态就等于在那段时间里把每一条一次性任务都永久标 `failed`,
|
|
167
|
+
* 运维改好配置重新部署也捞不回来了(行已不在 pending,`PUT /update-message`
|
|
168
|
+
* 回 409)。所以留在退避阶梯上——配置一修好,还在阶梯上的任务下一跳就正常发
|
|
169
|
+
* 出去。这跟 VAPID 配错回的 400/401/403 是同一个道理,见
|
|
170
|
+
* {@link PUSH_PAYLOAD_TOO_LARGE_STATUS} 那段注释。
|
|
171
|
+
*
|
|
172
|
+
* 带 `code` 但不带 `permanent`:失败原因照旧进 last_error 的 `errorCode`,宿主
|
|
173
|
+
* 想分流照样读得到,只是不再跳过重试。
|
|
174
|
+
*/
|
|
175
|
+
export class DeploymentConfigError extends Error {
|
|
176
|
+
/**
|
|
177
|
+
* @param {string} message
|
|
178
|
+
* @param {{ code?: string, cause?: unknown }} [options]
|
|
179
|
+
*/
|
|
180
|
+
constructor(message: string, options?: {
|
|
181
|
+
code?: string;
|
|
182
|
+
cause?: unknown;
|
|
183
|
+
});
|
|
184
|
+
code: string;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* 投递期间发现「这条任务已经不归本次投递管了」时,推送侧抛的错误码:行被
|
|
188
|
+
* `DELETE /message` 取消、被 `supersedesUuid` 顶替,或被别的执行者收尾了。
|
|
189
|
+
*
|
|
190
|
+
* 发送方(message-processor 的正文投递、agentic-fire 的 hook 投递)靠它区分
|
|
191
|
+
* 「取消」和「发失败」——两者的收尾完全不同:取消要把这一批还没发出去的
|
|
192
|
+
* outbox 行撤掉,发失败则要把它们留着等补收。
|
|
193
|
+
*/
|
|
194
|
+
export const TASK_CANCELLED_CODE: "TASK_CANCELLED";
|
|
76
195
|
export type ErrorCause = {
|
|
77
196
|
/**
|
|
78
197
|
* - 在哪一段炸的
|
|
@@ -83,9 +202,12 @@ export type ErrorCause = {
|
|
|
83
202
|
*/
|
|
84
203
|
name: string;
|
|
85
204
|
/**
|
|
86
|
-
* -
|
|
205
|
+
* - 脱敏后的错误消息。降级 500(配置都没建起来那条
|
|
206
|
+
* 路)回给跨域调用方时不带这个字段——那条路的 CORS 头是回显来访 Origin 的,任
|
|
207
|
+
* 意第三方页面都能读,而构建期异常原文里常有 binding 名、内网域名、环境变量
|
|
208
|
+
* 名。同源 / 无 Origin 的请求照旧带全文,`wrangler tail` 里也一直有。
|
|
87
209
|
*/
|
|
88
|
-
message
|
|
210
|
+
message?: string;
|
|
89
211
|
/**
|
|
90
212
|
* - 错误自带的 `code` 字符串(有才带)
|
|
91
213
|
*/
|