@sema-agent/server 7.73.0 → 7.73.1

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.
@@ -1,5 +1,5 @@
1
1
  import { canAskTransition } from "../approval-ask-machine.js";
2
- import { assertIdempotencyKeyShape, ApprovalAskReadAbortedError, projectAskTerminalClaimTruth } from "./approval-ask-store-sql.js";
2
+ import { assertIdempotencyKeyShape, assertIntegralEpochMs, ApprovalAskReadAbortedError, projectAskTerminalClaimTruth } from "./approval-ask-store-sql.js";
3
3
  function applyPatch(row, patch) {
4
4
  if (patch.decision !== undefined)
5
5
  row.decision = patch.decision;
@@ -24,6 +24,8 @@ export class InMemoryApprovalAskStore {
24
24
  asks = new Map();
25
25
  batches = new Map();
26
26
  async ensureAsk(row) {
27
+ assertIntegralEpochMs("expiresAtMs", row.expiresAtMs);
28
+ assertIntegralEpochMs("createdAtMs", row.createdAtMs);
27
29
  if (!this.batches.has(row.batchId)) {
28
30
  this.batches.set(row.batchId, {
29
31
  batchId: row.batchId,
@@ -226,6 +226,11 @@ export type DecideResult = {
226
226
  * `idempotency_conflict`/回放结果。键是调用方铸的 opaque 值,首尾空白没有任何合法语义,
227
227
  * 在边界上 fail-loud 拒掉,方言分歧面整个消失(比把列改 VARBINARY 更窄、且对三形同时成立)。
228
228
  */
229
+ /** BIGINT 毫秒列的整数守卫(两 twin 同一只):`expires_at_ms` / `created_at_ms` / `updated_at_ms` 落库前必须是
230
+ * 安全整数。带小数的墙钟(`Date.now() + performance.now()` 派生窗)在 PG 上被 `bigint` 拒收、在 MySQL 协议上被
231
+ * 隐式截断 —— 两方言不同答;这里改成两方言同一句 TypeError(响亮,点名字段与值),铸点侧(`tool-approval.ts`
232
+ * 的 deadline 铸点)负责给整数,本守卫只拦漏网。 */
233
+ export declare function assertIntegralEpochMs(field: string, value: number): void;
229
234
  export declare function assertIdempotencyKeyShape(key: string): void;
230
235
  /**
231
236
  * [ref] 车3 刀 3b(§14.2 遗留记账):两条**重放读口**被调用方的 deadline 掐断时抛的具名错误。
@@ -1,6 +1,11 @@
1
1
  import { mysqlDriver, pgDriver, dialectJsonEncoder } from "./sql-driver.js";
2
2
  import { canAskTransition } from "../approval-ask-machine.js";
3
3
  import { isDupKeyError, isMissingColumnError } from "./sql-errors.js";
4
+ export function assertIntegralEpochMs(field, value) {
5
+ if (!Number.isSafeInteger(value)) {
6
+ throw new TypeError(`approval-ask store: ${field} must be an integer epoch-ms (BIGINT column), got ${String(value)}`);
7
+ }
8
+ }
4
9
  export function assertIdempotencyKeyShape(key) {
5
10
  if (key.length === 0 || key.length > 255 || key.trim() !== key) {
6
11
  throw new Error(`invalid idempotency key: must be 1-255 chars with no leading/trailing whitespace (got ${JSON.stringify(key.slice(0, 32))}${key.length > 32 ? "…" : ""}, length ${key.length})`);
@@ -314,6 +319,8 @@ export class SqlApprovalAskStore {
314
319
  return rows[0] ? mapBatchRow(rows[0]) : null;
315
320
  }
316
321
  async ensureAsk(row) {
322
+ assertIntegralEpochMs("expiresAtMs", row.expiresAtMs);
323
+ assertIntegralEpochMs("createdAtMs", row.createdAtMs);
317
324
  const now = row.createdAtMs;
318
325
  let insertedRows = 0;
319
326
  const conn = await this.db.connect();
@@ -852,7 +852,7 @@ export class ToolApprovalCoordinator {
852
852
  };
853
853
  const windowBudgetMs = reachability === "unreached" ? this.unreachedTtlMs : this.ttlMs;
854
854
  const effectiveWindowMs = effectiveAskWindowMs(windowBudgetMs, this.windowMarginMs, origin.legDeadlineMonotonic, performance.now());
855
- const expiresAtMs = Date.now() + effectiveWindowMs;
855
+ const expiresAtMs = Math.ceil(Date.now() + effectiveWindowMs);
856
856
  let askId;
857
857
  let batchId;
858
858
  const card = this.askStore ? buildApprovalCard(frame, req, req.requiresRealApproval === true) : undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/server",
3
- "version": "7.73.0",
3
+ "version": "7.73.1",
4
4
  "description": "Sema Server — the server/API implementation layer for Sema, wiring core, registry, model providers, and cloud agent execution. Built on @sema-agent/core.",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",