@rei-standard/amsg-server 2.6.0-next.2 → 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.
Files changed (85) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +599 -24
  3. package/dist/adapters/d1.d.ts +416 -0
  4. package/dist/adapters/factory.d.ts +39 -0
  5. package/dist/adapters/interface.d.ts +306 -0
  6. package/dist/adapters/neon.d.ts +88 -0
  7. package/dist/adapters/pg-shared.d.ts +161 -0
  8. package/dist/adapters/pg.d.ts +84 -0
  9. package/dist/adapters/schema.d.ts +57 -0
  10. package/dist/adapters/schema.sqlite.d.ts +49 -0
  11. package/dist/chunk-7NMQFTDJ.cjs +148 -0
  12. package/dist/chunk-E7OWP3VL.cjs +135 -0
  13. package/dist/chunk-GN44PST5.mjs +148 -0
  14. package/dist/chunk-KOJQVOYS.mjs +5847 -0
  15. package/dist/chunk-QHVID3V2.cjs +5847 -0
  16. package/dist/chunk-ZGGF4GMA.mjs +135 -0
  17. package/dist/cloudflare/single-user-worker.d.ts +37 -0
  18. package/dist/cloudflare.cjs +39 -2
  19. package/dist/cloudflare.d.ts +10 -2
  20. package/dist/cloudflare.mjs +40 -3
  21. package/dist/handlers/cancel-message.d.ts +3 -0
  22. package/dist/handlers/capabilities.d.ts +4 -0
  23. package/dist/handlers/client-state.d.ts +7 -0
  24. package/dist/handlers/get-message.d.ts +3 -0
  25. package/dist/handlers/get-user-key.d.ts +3 -0
  26. package/dist/handlers/init-tenant.d.ts +23 -0
  27. package/dist/handlers/llm-credentials.d.ts +5 -0
  28. package/dist/handlers/messages.d.ts +3 -0
  29. package/dist/handlers/outbox.d.ts +7 -0
  30. package/dist/handlers/push-subscription.d.ts +5 -0
  31. package/dist/handlers/schedule-message.d.ts +3 -0
  32. package/dist/handlers/send-notifications.d.ts +3 -0
  33. package/dist/handlers/single-user-init.d.ts +13 -0
  34. package/dist/handlers/update-message.d.ts +3 -0
  35. package/dist/handlers/vapid-public-key.d.ts +19 -0
  36. package/dist/index.cjs +133 -44
  37. package/dist/index.d.cts +131 -766
  38. package/dist/index.d.ts +131 -766
  39. package/dist/index.mjs +125 -36
  40. package/dist/lib/agentic-fire.d.ts +108 -0
  41. package/dist/lib/client-state-store.d.ts +80 -0
  42. package/dist/lib/constant-time.d.ts +14 -0
  43. package/dist/lib/db-errors.d.ts +10 -0
  44. package/dist/lib/encryption.d.ts +48 -0
  45. package/dist/lib/errors.d.ts +215 -0
  46. package/dist/lib/llm-credentials-store.d.ts +147 -0
  47. package/dist/lib/llm.d.ts +1 -0
  48. package/dist/lib/message-processor.d.ts +73 -0
  49. package/dist/lib/outbox-store.d.ts +95 -0
  50. package/dist/lib/push-subscription-store.d.ts +94 -0
  51. package/dist/lib/recurrence.d.ts +51 -0
  52. package/dist/lib/request.d.ts +182 -0
  53. package/dist/lib/result-emitter.d.ts +54 -0
  54. package/dist/lib/run-tick.d.ts +115 -0
  55. package/dist/lib/schema-version.d.ts +50 -0
  56. package/dist/lib/state-accessors.d.ts +70 -0
  57. package/dist/lib/state-chunks.d.ts +55 -0
  58. package/dist/lib/task-projection.d.ts +92 -0
  59. package/dist/lib/validation.d.ts +97 -0
  60. package/dist/lib/version.d.ts +7 -0
  61. package/dist/lib/webcrypto-utils.d.ts +1 -0
  62. package/dist/lib/webpush-webcrypto.d.ts +78 -0
  63. package/dist/{neon-BFUS25UX.cjs → neon-KP2CPA57.cjs} +110 -10
  64. package/dist/{neon-CU5N3CSW.mjs → neon-ZIMHALYI.mjs} +106 -6
  65. package/dist/{pg-QO6NKTGL.mjs → pg-QGC2XHUT.mjs} +94 -5
  66. package/dist/{pg-IIH3M4OM.cjs → pg-RZPQGXR3.cjs} +98 -9
  67. package/dist/single-user.d.ts +95 -0
  68. package/dist/tenant/blob-store.d.ts +30 -0
  69. package/dist/tenant/context.d.ts +47 -0
  70. package/dist/tenant/single-user-context.d.ts +29 -0
  71. package/dist/tenant/token.d.ts +26 -0
  72. package/package.json +3 -3
  73. package/dist/chunk-5ENJGVZX.mjs +0 -72
  74. package/dist/chunk-GN5QTMCL.cjs +0 -1870
  75. package/dist/chunk-PVNLB6TF.mjs +0 -1870
  76. package/dist/chunk-RGECD4OH.cjs +0 -72
  77. package/dist/cloudflare-B-E51VjP.d.cts +0 -2848
  78. package/dist/cloudflare-B-E51VjP.d.ts +0 -2848
  79. package/dist/cloudflare.d.cts +0 -2
  80. package/dist/neon-CJl66EGy.d.cts +0 -251
  81. package/dist/neon-DYvGnCzx.d.ts +0 -251
  82. package/dist/pg-07S-u_H4.d.cts +0 -246
  83. package/dist/pg-Du-pN_UT.d.ts +0 -246
  84. package/dist/schema-C8OnYk6j.d.cts +0 -74
  85. package/dist/schema-C8OnYk6j.d.ts +0 -74
@@ -1,9 +1,27 @@
1
+ import {
2
+ claimTask,
3
+ deleteLlmCredentials,
4
+ deletePushSubscription,
5
+ getLlmCredentials,
6
+ getPushSubscription,
7
+ getTaskStatusInfo,
8
+ listLlmCredentials,
9
+ renewTaskLease,
10
+ upsertLlmCredentials,
11
+ upsertPushSubscription
12
+ } from "./chunk-ZGGF4GMA.mjs";
1
13
  import {
2
14
  COLUMNS_SQL,
3
15
  INDEXES,
16
+ LLM_CREDENTIALS_TABLE_SQL,
17
+ MIGRATIONS,
18
+ PUSH_SUBSCRIPTION_TABLE_SQL,
4
19
  TABLE_SQL,
20
+ TASK_DELIVERY_COLUMNS,
21
+ TASK_DETAIL_COLUMNS,
22
+ UPDATABLE_COLUMNS,
5
23
  VERIFY_TABLE_SQL
6
- } from "./chunk-5ENJGVZX.mjs";
24
+ } from "./chunk-GN44PST5.mjs";
7
25
 
8
26
  // src/server/adapters/pg.js
9
27
  import { Pool } from "pg";
@@ -17,6 +35,12 @@ var PgAdapter = class {
17
35
  _getPool() {
18
36
  if (!this._pool) {
19
37
  this._pool = new Pool({ connectionString: this._connectionString });
38
+ this._pool.on("error", (error) => {
39
+ console.error(
40
+ "[amsg-server pg] \u8FDE\u63A5\u6C60\u91CC\u7684\u7A7A\u95F2\u8FDE\u63A5\u51FA\u9519\uFF08\u8BE5\u8FDE\u63A5\u5DF2\u88AB\u6458\u9664\uFF0C\u4E0B\u6B21\u67E5\u8BE2\u4F1A\u91CD\u8FDE\uFF09:",
41
+ error && error.message
42
+ );
43
+ });
20
44
  }
21
45
  return this._pool;
22
46
  }
@@ -28,6 +52,11 @@ var PgAdapter = class {
28
52
  }
29
53
  async initSchema() {
30
54
  await this._query(TABLE_SQL);
55
+ await this._query(PUSH_SUBSCRIPTION_TABLE_SQL);
56
+ await this._query(LLM_CREDENTIALS_TABLE_SQL);
57
+ for (const migration of MIGRATIONS) {
58
+ await this._query(migration.sql);
59
+ }
31
60
  const indexResults = [];
32
61
  for (const index of INDEXES) {
33
62
  try {
@@ -72,6 +101,8 @@ var PgAdapter = class {
72
101
  }
73
102
  async dropSchema() {
74
103
  await this._query("DROP TABLE IF EXISTS scheduled_messages CASCADE");
104
+ await this._query("DROP TABLE IF EXISTS push_subscriptions CASCADE");
105
+ await this._query("DROP TABLE IF EXISTS llm_credentials CASCADE");
75
106
  }
76
107
  async createTask(params) {
77
108
  const rows = await this._query(
@@ -85,7 +116,7 @@ var PgAdapter = class {
85
116
  }
86
117
  async getTaskByUuid(uuid, userId) {
87
118
  const rows = await this._query(
88
- `SELECT id, user_id, uuid, encrypted_payload, message_type, next_send_at, status, retry_count
119
+ `SELECT ${TASK_DETAIL_COLUMNS}
89
120
  FROM scheduled_messages
90
121
  WHERE uuid = $1 AND user_id = $2 AND status = 'pending'
91
122
  LIMIT 1`,
@@ -95,7 +126,7 @@ var PgAdapter = class {
95
126
  }
96
127
  async getTaskByUuidOnly(uuid) {
97
128
  const rows = await this._query(
98
- `SELECT id, user_id, uuid, encrypted_payload, message_type, next_send_at, status, retry_count
129
+ `SELECT ${TASK_DELIVERY_COLUMNS}
99
130
  FROM scheduled_messages
100
131
  WHERE uuid = $1 AND status = 'pending'
101
132
  LIMIT 1`,
@@ -103,11 +134,28 @@ var PgAdapter = class {
103
134
  );
104
135
  return rows[0] || null;
105
136
  }
137
+ /**
138
+ * 这条 uuid 现在是什么状态——不限用户,也不限状态(上面那个只看 pending
139
+ * 行)。`runTask` 用它把「这条已经跑完了」和「压根没这条」分开回报。
140
+ *
141
+ * @param {string} uuid
142
+ * @returns {Promise<{ status: string }|null>}
143
+ */
144
+ async getTaskStatusByUuidOnly(uuid) {
145
+ const rows = await this._query(
146
+ `SELECT status FROM scheduled_messages WHERE uuid = $1 LIMIT 1`,
147
+ [uuid]
148
+ );
149
+ return rows[0] ? { status: rows[0].status } : null;
150
+ }
106
151
  async updateTaskById(taskId, updates) {
107
152
  const sets = [];
108
153
  const values = [];
109
154
  let idx = 1;
110
155
  for (const [key, value] of Object.entries(updates)) {
156
+ if (!UPDATABLE_COLUMNS.has(key)) {
157
+ throw new Error(`[amsg-server pg] rejected unknown update column: ${key}`);
158
+ }
111
159
  sets.push(`${key} = $${idx}`);
112
160
  values.push(value);
113
161
  idx++;
@@ -126,6 +174,9 @@ var PgAdapter = class {
126
174
  let idx = 2;
127
175
  if (extraFields) {
128
176
  for (const [key, value] of Object.entries(extraFields)) {
177
+ if (!UPDATABLE_COLUMNS.has(key)) {
178
+ throw new Error(`[amsg-server pg] rejected unknown update column: ${key}`);
179
+ }
129
180
  sets.push(`${key} = $${idx}`);
130
181
  values.push(value);
131
182
  idx++;
@@ -153,14 +204,25 @@ var PgAdapter = class {
153
204
  }
154
205
  async getPendingTasks(limit = 50) {
155
206
  return this._query(
156
- `SELECT id, user_id, uuid, encrypted_payload, message_type, next_send_at, status, retry_count
207
+ `SELECT ${TASK_DELIVERY_COLUMNS}
157
208
  FROM scheduled_messages
158
209
  WHERE status = 'pending' AND next_send_at <= NOW()
210
+ AND (lease_until IS NULL OR lease_until <= NOW())
211
+ AND (retry_after IS NULL OR retry_after <= NOW())
159
212
  ORDER BY next_send_at ASC
160
213
  LIMIT $1`,
161
214
  [limit]
162
215
  );
163
216
  }
217
+ // 领取一条到点的任务。SQL 与并发语义在 pg-shared.js(pg / neon 共用一份,
218
+ // 语义说明也在那里)。
219
+ async claimTask(taskId, expectedNextSendAt, leaseUntil, serializeGroup = null) {
220
+ return claimTask((text, params) => this._query(text, params), taskId, expectedNextSendAt, leaseUntil, serializeGroup);
221
+ }
222
+ // 投递期间的租约续期(run-tick 心跳;语义见 pg-shared.js)。
223
+ async renewTaskLease(taskId, leaseUntil) {
224
+ return renewTaskLease((text, params) => this._query(text, params), taskId, leaseUntil);
225
+ }
164
226
  async listTasks(userId, opts = {}) {
165
227
  const { status = "all", limit = 20, offset = 0 } = opts;
166
228
  const conditions = ["user_id = $1"];
@@ -179,7 +241,7 @@ var PgAdapter = class {
179
241
  const total = parseInt(countRows[0].count, 10);
180
242
  const taskParams = [...params, limit, offset];
181
243
  const tasks = await this._query(
182
- `SELECT id, user_id, uuid, encrypted_payload, message_type, next_send_at, status, retry_count, created_at, updated_at
244
+ `SELECT ${TASK_DETAIL_COLUMNS}
183
245
  FROM scheduled_messages
184
246
  WHERE ${where}
185
247
  ORDER BY next_send_at ASC
@@ -206,6 +268,33 @@ var PgAdapter = class {
206
268
  );
207
269
  return rows.length > 0 ? rows[0].status : null;
208
270
  }
271
+ // 状态 + 失败摘要(GET /message 对已失败的行透出原因;语义见 pg-shared.js)。
272
+ async getTaskStatusInfo(uuid, userId) {
273
+ return getTaskStatusInfo((text, params) => this._query(text, params), uuid, userId);
274
+ }
275
+ // ── push_subscriptions(实现见 pg-shared.js,pg / neon 共用一份)─────────
276
+ async getPushSubscription(userId) {
277
+ return getPushSubscription((text, params) => this._query(text, params), userId);
278
+ }
279
+ async upsertPushSubscription(userId, encryptedSubscription, updatedAt) {
280
+ return upsertPushSubscription((text, params) => this._query(text, params), userId, encryptedSubscription, updatedAt);
281
+ }
282
+ async deletePushSubscription(userId) {
283
+ return deletePushSubscription((text, params) => this._query(text, params), userId);
284
+ }
285
+ // ── llm_credentials(实现见 pg-shared.js,pg / neon 共用一份)───────────
286
+ async upsertLlmCredentials(userId, entries) {
287
+ return upsertLlmCredentials((text, params) => this._query(text, params), userId, entries, (/* @__PURE__ */ new Date()).toISOString());
288
+ }
289
+ async getLlmCredentials(userId, credIds) {
290
+ return getLlmCredentials((text, params) => this._query(text, params), userId, credIds);
291
+ }
292
+ async listLlmCredentials(userId) {
293
+ return listLlmCredentials((text, params) => this._query(text, params), userId);
294
+ }
295
+ async deleteLlmCredentials(userId, credIds = null) {
296
+ return deleteLlmCredentials((text, params) => this._query(text, params), userId, credIds);
297
+ }
209
298
  };
210
299
  export {
211
300
  PgAdapter
@@ -3,7 +3,25 @@
3
3
 
4
4
 
5
5
 
6
- var _chunkRGECD4OHcjs = require('./chunk-RGECD4OH.cjs');
6
+
7
+
8
+
9
+
10
+
11
+
12
+ var _chunkE7OWP3VLcjs = require('./chunk-E7OWP3VL.cjs');
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+ var _chunk7NMQFTDJcjs = require('./chunk-7NMQFTDJ.cjs');
7
25
 
8
26
  // src/server/adapters/pg.js
9
27
  var _pg = require('pg');
@@ -17,6 +35,12 @@ var PgAdapter = class {
17
35
  _getPool() {
18
36
  if (!this._pool) {
19
37
  this._pool = new (0, _pg.Pool)({ connectionString: this._connectionString });
38
+ this._pool.on("error", (error) => {
39
+ console.error(
40
+ "[amsg-server pg] \u8FDE\u63A5\u6C60\u91CC\u7684\u7A7A\u95F2\u8FDE\u63A5\u51FA\u9519\uFF08\u8BE5\u8FDE\u63A5\u5DF2\u88AB\u6458\u9664\uFF0C\u4E0B\u6B21\u67E5\u8BE2\u4F1A\u91CD\u8FDE\uFF09:",
41
+ error && error.message
42
+ );
43
+ });
20
44
  }
21
45
  return this._pool;
22
46
  }
@@ -27,9 +51,14 @@ var PgAdapter = class {
27
51
  return result.rows;
28
52
  }
29
53
  async initSchema() {
30
- await this._query(_chunkRGECD4OHcjs.TABLE_SQL);
54
+ await this._query(_chunk7NMQFTDJcjs.TABLE_SQL);
55
+ await this._query(_chunk7NMQFTDJcjs.PUSH_SUBSCRIPTION_TABLE_SQL);
56
+ await this._query(_chunk7NMQFTDJcjs.LLM_CREDENTIALS_TABLE_SQL);
57
+ for (const migration of _chunk7NMQFTDJcjs.MIGRATIONS) {
58
+ await this._query(migration.sql);
59
+ }
31
60
  const indexResults = [];
32
- for (const index of _chunkRGECD4OHcjs.INDEXES) {
61
+ for (const index of _chunk7NMQFTDJcjs.INDEXES) {
33
62
  try {
34
63
  await this._query(index.sql);
35
64
  indexResults.push({
@@ -55,11 +84,11 @@ var PgAdapter = class {
55
84
  `Critical index creation failed (${failedNames}). Please remove duplicate UUID rows and run initSchema again.`
56
85
  );
57
86
  }
58
- const tableCheck = await this._query(_chunkRGECD4OHcjs.VERIFY_TABLE_SQL);
87
+ const tableCheck = await this._query(_chunk7NMQFTDJcjs.VERIFY_TABLE_SQL);
59
88
  if (tableCheck.length === 0) {
60
89
  throw new Error("Table creation verification failed");
61
90
  }
62
- const columns = await this._query(_chunkRGECD4OHcjs.COLUMNS_SQL);
91
+ const columns = await this._query(_chunk7NMQFTDJcjs.COLUMNS_SQL);
63
92
  return {
64
93
  columnsCreated: columns.length,
65
94
  indexesCreated: indexResults.filter((r) => r.status === "success").length,
@@ -72,6 +101,8 @@ var PgAdapter = class {
72
101
  }
73
102
  async dropSchema() {
74
103
  await this._query("DROP TABLE IF EXISTS scheduled_messages CASCADE");
104
+ await this._query("DROP TABLE IF EXISTS push_subscriptions CASCADE");
105
+ await this._query("DROP TABLE IF EXISTS llm_credentials CASCADE");
75
106
  }
76
107
  async createTask(params) {
77
108
  const rows = await this._query(
@@ -85,7 +116,7 @@ var PgAdapter = class {
85
116
  }
86
117
  async getTaskByUuid(uuid, userId) {
87
118
  const rows = await this._query(
88
- `SELECT id, user_id, uuid, encrypted_payload, message_type, next_send_at, status, retry_count
119
+ `SELECT ${_chunk7NMQFTDJcjs.TASK_DETAIL_COLUMNS}
89
120
  FROM scheduled_messages
90
121
  WHERE uuid = $1 AND user_id = $2 AND status = 'pending'
91
122
  LIMIT 1`,
@@ -95,7 +126,7 @@ var PgAdapter = class {
95
126
  }
96
127
  async getTaskByUuidOnly(uuid) {
97
128
  const rows = await this._query(
98
- `SELECT id, user_id, uuid, encrypted_payload, message_type, next_send_at, status, retry_count
129
+ `SELECT ${_chunk7NMQFTDJcjs.TASK_DELIVERY_COLUMNS}
99
130
  FROM scheduled_messages
100
131
  WHERE uuid = $1 AND status = 'pending'
101
132
  LIMIT 1`,
@@ -103,11 +134,28 @@ var PgAdapter = class {
103
134
  );
104
135
  return rows[0] || null;
105
136
  }
137
+ /**
138
+ * 这条 uuid 现在是什么状态——不限用户,也不限状态(上面那个只看 pending
139
+ * 行)。`runTask` 用它把「这条已经跑完了」和「压根没这条」分开回报。
140
+ *
141
+ * @param {string} uuid
142
+ * @returns {Promise<{ status: string }|null>}
143
+ */
144
+ async getTaskStatusByUuidOnly(uuid) {
145
+ const rows = await this._query(
146
+ `SELECT status FROM scheduled_messages WHERE uuid = $1 LIMIT 1`,
147
+ [uuid]
148
+ );
149
+ return rows[0] ? { status: rows[0].status } : null;
150
+ }
106
151
  async updateTaskById(taskId, updates) {
107
152
  const sets = [];
108
153
  const values = [];
109
154
  let idx = 1;
110
155
  for (const [key, value] of Object.entries(updates)) {
156
+ if (!_chunk7NMQFTDJcjs.UPDATABLE_COLUMNS.has(key)) {
157
+ throw new Error(`[amsg-server pg] rejected unknown update column: ${key}`);
158
+ }
111
159
  sets.push(`${key} = $${idx}`);
112
160
  values.push(value);
113
161
  idx++;
@@ -126,6 +174,9 @@ var PgAdapter = class {
126
174
  let idx = 2;
127
175
  if (extraFields) {
128
176
  for (const [key, value] of Object.entries(extraFields)) {
177
+ if (!_chunk7NMQFTDJcjs.UPDATABLE_COLUMNS.has(key)) {
178
+ throw new Error(`[amsg-server pg] rejected unknown update column: ${key}`);
179
+ }
129
180
  sets.push(`${key} = $${idx}`);
130
181
  values.push(value);
131
182
  idx++;
@@ -153,14 +204,25 @@ var PgAdapter = class {
153
204
  }
154
205
  async getPendingTasks(limit = 50) {
155
206
  return this._query(
156
- `SELECT id, user_id, uuid, encrypted_payload, message_type, next_send_at, status, retry_count
207
+ `SELECT ${_chunk7NMQFTDJcjs.TASK_DELIVERY_COLUMNS}
157
208
  FROM scheduled_messages
158
209
  WHERE status = 'pending' AND next_send_at <= NOW()
210
+ AND (lease_until IS NULL OR lease_until <= NOW())
211
+ AND (retry_after IS NULL OR retry_after <= NOW())
159
212
  ORDER BY next_send_at ASC
160
213
  LIMIT $1`,
161
214
  [limit]
162
215
  );
163
216
  }
217
+ // 领取一条到点的任务。SQL 与并发语义在 pg-shared.js(pg / neon 共用一份,
218
+ // 语义说明也在那里)。
219
+ async claimTask(taskId, expectedNextSendAt, leaseUntil, serializeGroup = null) {
220
+ return _chunkE7OWP3VLcjs.claimTask.call(void 0, (text, params) => this._query(text, params), taskId, expectedNextSendAt, leaseUntil, serializeGroup);
221
+ }
222
+ // 投递期间的租约续期(run-tick 心跳;语义见 pg-shared.js)。
223
+ async renewTaskLease(taskId, leaseUntil) {
224
+ return _chunkE7OWP3VLcjs.renewTaskLease.call(void 0, (text, params) => this._query(text, params), taskId, leaseUntil);
225
+ }
164
226
  async listTasks(userId, opts = {}) {
165
227
  const { status = "all", limit = 20, offset = 0 } = opts;
166
228
  const conditions = ["user_id = $1"];
@@ -179,7 +241,7 @@ var PgAdapter = class {
179
241
  const total = parseInt(countRows[0].count, 10);
180
242
  const taskParams = [...params, limit, offset];
181
243
  const tasks = await this._query(
182
- `SELECT id, user_id, uuid, encrypted_payload, message_type, next_send_at, status, retry_count, created_at, updated_at
244
+ `SELECT ${_chunk7NMQFTDJcjs.TASK_DETAIL_COLUMNS}
183
245
  FROM scheduled_messages
184
246
  WHERE ${where}
185
247
  ORDER BY next_send_at ASC
@@ -206,6 +268,33 @@ var PgAdapter = class {
206
268
  );
207
269
  return rows.length > 0 ? rows[0].status : null;
208
270
  }
271
+ // 状态 + 失败摘要(GET /message 对已失败的行透出原因;语义见 pg-shared.js)。
272
+ async getTaskStatusInfo(uuid, userId) {
273
+ return _chunkE7OWP3VLcjs.getTaskStatusInfo.call(void 0, (text, params) => this._query(text, params), uuid, userId);
274
+ }
275
+ // ── push_subscriptions(实现见 pg-shared.js,pg / neon 共用一份)─────────
276
+ async getPushSubscription(userId) {
277
+ return _chunkE7OWP3VLcjs.getPushSubscription.call(void 0, (text, params) => this._query(text, params), userId);
278
+ }
279
+ async upsertPushSubscription(userId, encryptedSubscription, updatedAt) {
280
+ return _chunkE7OWP3VLcjs.upsertPushSubscription.call(void 0, (text, params) => this._query(text, params), userId, encryptedSubscription, updatedAt);
281
+ }
282
+ async deletePushSubscription(userId) {
283
+ return _chunkE7OWP3VLcjs.deletePushSubscription.call(void 0, (text, params) => this._query(text, params), userId);
284
+ }
285
+ // ── llm_credentials(实现见 pg-shared.js,pg / neon 共用一份)───────────
286
+ async upsertLlmCredentials(userId, entries) {
287
+ return _chunkE7OWP3VLcjs.upsertLlmCredentials.call(void 0, (text, params) => this._query(text, params), userId, entries, (/* @__PURE__ */ new Date()).toISOString());
288
+ }
289
+ async getLlmCredentials(userId, credIds) {
290
+ return _chunkE7OWP3VLcjs.getLlmCredentials.call(void 0, (text, params) => this._query(text, params), userId, credIds);
291
+ }
292
+ async listLlmCredentials(userId) {
293
+ return _chunkE7OWP3VLcjs.listLlmCredentials.call(void 0, (text, params) => this._query(text, params), userId);
294
+ }
295
+ async deleteLlmCredentials(userId, credIds = null) {
296
+ return _chunkE7OWP3VLcjs.deleteLlmCredentials.call(void 0, (text, params) => this._query(text, params), userId, credIds);
297
+ }
209
298
  };
210
299
 
211
300
 
@@ -0,0 +1,95 @@
1
+ export function createSingleUserServer(config: any): {
2
+ ctx: {
3
+ vapid: {
4
+ email: any;
5
+ publicKey: any;
6
+ privateKey: any;
7
+ };
8
+ webpush: any;
9
+ multipart: any;
10
+ tenantManager: {
11
+ resolveTenant: (headers: any) => Promise<{
12
+ ok: boolean;
13
+ error: {
14
+ status: number;
15
+ body: {
16
+ success: boolean;
17
+ error: {
18
+ code: string;
19
+ message: string;
20
+ };
21
+ };
22
+ };
23
+ context?: undefined;
24
+ } | {
25
+ ok: boolean;
26
+ context: {
27
+ tenantId: string;
28
+ tokenType: string;
29
+ db: any;
30
+ masterKey: any;
31
+ };
32
+ error?: undefined;
33
+ }>;
34
+ initializeTenant: () => Promise<{
35
+ tenantId: string;
36
+ schema: any;
37
+ }>;
38
+ };
39
+ hooks: any;
40
+ maxToolIterations: any;
41
+ totalTimeoutMs: any;
42
+ maxStateValueBytes: any;
43
+ onAfterSend: any;
44
+ onFireSettled: any;
45
+ maxScheduledTasksPerFire: any;
46
+ };
47
+ handlers: {
48
+ init: {
49
+ POST: Function;
50
+ };
51
+ getUserKey: {
52
+ GET: (url: any, headers: any) => Promise<any>;
53
+ };
54
+ scheduleMessage: {
55
+ POST: (headers: any, body: any) => Promise<any>;
56
+ };
57
+ updateMessage: {
58
+ PUT: (url: any, headers: any, body: any) => Promise<any>;
59
+ };
60
+ cancelMessage: {
61
+ DELETE: (url: any, headers: any) => Promise<any>;
62
+ };
63
+ messages: {
64
+ GET: (url: any, headers: any) => Promise<any>;
65
+ };
66
+ getMessage: {
67
+ GET: (url: any, headers: any) => Promise<any>;
68
+ };
69
+ vapidPublicKey: {
70
+ GET: Function;
71
+ };
72
+ clientState: {
73
+ PUT: (headers: any, body: any) => Promise<any>;
74
+ GET: (url: any, headers: any) => Promise<any>;
75
+ DELETE: (url: any, headers: any) => Promise<any>;
76
+ };
77
+ pushSubscription: {
78
+ PUT: (headers: any, body: any) => Promise<any>;
79
+ GET: (url: any, headers: any) => Promise<any>;
80
+ DELETE: (url: any, headers: any) => Promise<any>;
81
+ };
82
+ llmCredentials: {
83
+ PUT: (headers: any, body: any) => Promise<any>;
84
+ GET: (url: any, headers: any) => Promise<any>;
85
+ DELETE: (url: any, headers: any, body: any) => Promise<any>;
86
+ };
87
+ capabilities: {
88
+ GET: (url: any, headers: any) => Promise<any>;
89
+ };
90
+ outbox: {
91
+ GET: (url: any, headers: any) => Promise<any>;
92
+ POST: (headers: any, body: any) => Promise<any>;
93
+ };
94
+ };
95
+ };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @typedef {{
3
+ * tenantId: string,
4
+ * db: { driver: 'neon'|'pg', connectionString: string },
5
+ * masterKey: string,
6
+ * createdAt: string,
7
+ * updatedAt: string
8
+ * }} TenantConfig
9
+ */
10
+ /**
11
+ * @param {{ namespace?: string, kek: string }} options
12
+ */
13
+ export function createTenantBlobStore(options: {
14
+ namespace?: string;
15
+ kek: string;
16
+ }): {
17
+ getTenantConfig(tenantId: any): Promise<any>;
18
+ setTenantConfig(config: any): Promise<void>;
19
+ deleteTenantConfig(tenantId: any): Promise<void>;
20
+ };
21
+ export type TenantConfig = {
22
+ tenantId: string;
23
+ db: {
24
+ driver: "neon" | "pg";
25
+ connectionString: string;
26
+ };
27
+ masterKey: string;
28
+ createdAt: string;
29
+ updatedAt: string;
30
+ };
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @param {{
3
+ * tenantStore: ReturnType<import('./blob-store.js').createTenantBlobStore>,
4
+ * tokenSigningKey: string,
5
+ * publicBaseUrl?: string
6
+ * }} options
7
+ */
8
+ export function createTenantContextManager(options: {
9
+ tenantStore: ReturnType<typeof import("./blob-store.js").createTenantBlobStore>;
10
+ tokenSigningKey: string;
11
+ publicBaseUrl?: string;
12
+ }): {
13
+ initializeTenant: ({ driver, connectionString, tenantId: providedTenantId }: {
14
+ driver: any;
15
+ connectionString: any;
16
+ tenantId: any;
17
+ }) => Promise<{
18
+ tenantId: string;
19
+ masterKeyFingerprint: string;
20
+ tenantToken: string;
21
+ cronToken: string;
22
+ cronWebhookUrl: string;
23
+ }>;
24
+ resolveTenant: (headers: any, options?: {}) => Promise<{
25
+ ok: boolean;
26
+ error: {
27
+ status: number;
28
+ body: {
29
+ success: boolean;
30
+ error: {
31
+ code: string;
32
+ message: string;
33
+ };
34
+ };
35
+ };
36
+ context?: undefined;
37
+ } | {
38
+ ok: boolean;
39
+ context: {
40
+ tenantId: any;
41
+ tokenType: any;
42
+ db: any;
43
+ masterKey: any;
44
+ };
45
+ error?: undefined;
46
+ }>;
47
+ };
@@ -0,0 +1,29 @@
1
+ export function createSingleUserContextManager({ db, masterKey, serverToken }?: {}): {
2
+ resolveTenant: (headers: any) => Promise<{
3
+ ok: boolean;
4
+ error: {
5
+ status: number;
6
+ body: {
7
+ success: boolean;
8
+ error: {
9
+ code: string;
10
+ message: string;
11
+ };
12
+ };
13
+ };
14
+ context?: undefined;
15
+ } | {
16
+ ok: boolean;
17
+ context: {
18
+ tenantId: string;
19
+ tokenType: string;
20
+ db: any;
21
+ masterKey: any;
22
+ };
23
+ error?: undefined;
24
+ }>;
25
+ initializeTenant: () => Promise<{
26
+ tenantId: string;
27
+ schema: any;
28
+ }>;
29
+ };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @typedef {'tenant'|'cron'} TokenType
3
+ */
4
+ /**
5
+ * @param {{ tenantId: string, type: TokenType, expiresInSeconds?: number }} params
6
+ * @param {string} secret
7
+ */
8
+ export function createTenantToken(params: {
9
+ tenantId: string;
10
+ type: TokenType;
11
+ expiresInSeconds?: number;
12
+ }, secret: string): string;
13
+ /**
14
+ * @param {string} token
15
+ * @param {string} secret
16
+ * @param {{ expectedTypes?: TokenType[] }} [options]
17
+ */
18
+ export function verifyTenantToken(token: string, secret: string, options?: {
19
+ expectedTypes?: TokenType[];
20
+ }): any;
21
+ /**
22
+ * @param {Record<string, any>} headers
23
+ * @returns {string}
24
+ */
25
+ export function extractBearerToken(headers?: Record<string, any>): string;
26
+ export type TokenType = "tenant" | "cron";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rei-standard/amsg-server",
3
- "version": "2.6.0-next.2",
3
+ "version": "2.6.0-next.21",
4
4
  "description": "ReiStandard Active Messaging server SDK with pluggable database adapters. Three-axis push schema (messageKind / messageType / messageSubtype) from @rei-standard/amsg-shared. Auto-emits ReasoningPush when the LLM response carries reasoning_content.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,7 +31,7 @@
31
31
  "dist"
32
32
  ],
33
33
  "scripts": {
34
- "build": "tsup",
34
+ "build": "tsup && tsc -p tsconfig.json && node -e \"require('fs').copyFileSync('dist/index.d.ts', 'dist/index.d.cts')\"",
35
35
  "test": "node --test test/*.test.mjs"
36
36
  },
37
37
  "engines": {
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "@netlify/blobs": "^8.1.0",
42
- "@rei-standard/amsg-shared": "^0.3.0",
42
+ "@rei-standard/amsg-shared": "^0.4.0-next.6",
43
43
  "web-push": "^3.6.7"
44
44
  },
45
45
  "peerDependencies": {