@sema-agent/server 7.82.1 → 7.83.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.
Files changed (73) hide show
  1. package/dist/bench/s1/arms.d.ts +4 -4
  2. package/dist/bench/s1/arms.js +1 -2
  3. package/dist/bench/s1/live-deps.js +0 -1
  4. package/dist/bench/s1/runner-ctx.d.ts +3 -3
  5. package/dist/bench/s1/tasks.d.ts +8 -4
  6. package/dist/config-catalog.js +0 -1
  7. package/dist/config.js +1 -0
  8. package/dist/leader/endpoint.js +2 -0
  9. package/dist/leader/leader.d.ts +33 -6
  10. package/dist/leader/leader.js +54 -45
  11. package/dist/leader/merge.d.ts +38 -29
  12. package/dist/leader/merge.js +45 -38
  13. package/dist/leader/wire.d.ts +2 -17
  14. package/dist/leader/wire.js +5 -58
  15. package/dist/observability/fail-open.d.ts +5 -5
  16. package/dist/observability/fail-open.js +5 -2
  17. package/dist/observability/run-terminal-log.d.ts +0 -7
  18. package/dist/observability/run-terminal-log.js +9 -20
  19. package/dist/plugins/adoption-log-sql.d.ts +3 -0
  20. package/dist/plugins/adoption-log-sql.js +5 -1
  21. package/dist/plugins/approval-ask-store-sql.d.ts +3 -0
  22. package/dist/plugins/approval-ask-store-sql.js +9 -5
  23. package/dist/plugins/background-agent-store-sql.d.ts +3 -0
  24. package/dist/plugins/background-agent-store-sql.js +7 -2
  25. package/dist/plugins/device-store-sql.d.ts +3 -0
  26. package/dist/plugins/device-store-sql.js +9 -4
  27. package/dist/plugins/ensure-index.d.ts +42 -0
  28. package/dist/plugins/ensure-index.js +81 -0
  29. package/dist/plugins/ensure-schema-lock-policy.d.ts +29 -0
  30. package/dist/plugins/ensure-schema-lock-policy.js +31 -0
  31. package/dist/plugins/image-bake-store-sql.d.ts +3 -0
  32. package/dist/plugins/image-bake-store-sql.js +6 -2
  33. package/dist/plugins/image-index-sql.d.ts +3 -0
  34. package/dist/plugins/image-index-sql.js +8 -4
  35. package/dist/plugins/leader-run-store-sql.d.ts +3 -0
  36. package/dist/plugins/leader-run-store-sql.js +6 -2
  37. package/dist/plugins/mailbox-store-sql.d.ts +3 -0
  38. package/dist/plugins/mailbox-store-sql.js +6 -1
  39. package/dist/plugins/memory-engine-pg.d.ts +4 -0
  40. package/dist/plugins/memory-engine-pg.js +6 -6
  41. package/dist/plugins/memory-engine-tidb.js +5 -0
  42. package/dist/plugins/memory-sync-store-pg.d.ts +5 -0
  43. package/dist/plugins/memory-sync-store-pg.js +9 -2
  44. package/dist/plugins/memory-sync-store-tidb.js +6 -0
  45. package/dist/plugins/one-time-migrations.d.ts +1 -1
  46. package/dist/plugins/one-time-migrations.js +7 -14
  47. package/dist/plugins/outcome-ledger-sql.d.ts +3 -0
  48. package/dist/plugins/outcome-ledger-sql.js +7 -3
  49. package/dist/plugins/permission-rule-store-sql.d.ts +3 -0
  50. package/dist/plugins/permission-rule-store-sql.js +9 -5
  51. package/dist/plugins/pg-cost-quota.d.ts +3 -0
  52. package/dist/plugins/pg-cost-quota.js +5 -1
  53. package/dist/plugins/pg-pool.d.ts +23 -2
  54. package/dist/plugins/pg-pool.js +22 -37
  55. package/dist/plugins/pg-rate-limiter.d.ts +3 -0
  56. package/dist/plugins/pg-rate-limiter.js +5 -1
  57. package/dist/plugins/pg-session-storage.d.ts +3 -0
  58. package/dist/plugins/pg-session-storage.js +8 -4
  59. package/dist/plugins/retention-store-sql.d.ts +3 -0
  60. package/dist/plugins/retention-store-sql.js +7 -3
  61. package/dist/plugins/roster-store-sql.d.ts +3 -0
  62. package/dist/plugins/roster-store-sql.js +6 -1
  63. package/dist/plugins/schema-indexes.d.ts +21 -0
  64. package/dist/plugins/schema-indexes.js +25 -0
  65. package/dist/plugins/task-attachment-store.d.ts +3 -0
  66. package/dist/plugins/task-attachment-store.js +7 -2
  67. package/dist/plugins/tidb-pool.d.ts +15 -3
  68. package/dist/plugins/tidb-pool.js +38 -15
  69. package/dist/plugins/tool-result-store-sql.d.ts +3 -0
  70. package/dist/plugins/tool-result-store-sql.js +5 -1
  71. package/dist/trace/project.d.ts +2 -1
  72. package/dist/trace/redact.d.ts +6 -0
  73. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  import mysql from "mysql2/promise";
2
2
  import type { Pool, PoolConnection } from "mysql2/promise";
3
3
  import type { ServiceConfig } from "../config-types.js";
4
+ import { type IndexSpec } from "./ensure-index.js";
4
5
  /**
5
6
  * Shared TiDB (MySQL wire-compatible) connection pool for the durable Session center (L1).
6
7
  * Owned by `main.ts`; closed on shutdown.
@@ -57,11 +58,22 @@ export declare const ENSURE_SCHEMA_LOCK = "sema_ensure_schema";
57
58
  * lock row — which both exhausts TiDB's "pessimistic lock retry limit" (surfacing as a thrown error) AND starves the
58
59
  * app's OWN `SELECT … FOR UPDATE` paths (image-bake admission/lease) of pessimistic-lock budget. So we acquire
59
60
  * NON-BLOCKING (GET_LOCK(name, 0) returns 0 immediately if held) and POLL with jittered backoff: one holder, the
60
- * rest sleeping (not blocked in-DB). Return false only after exhausting retries (the caller then DEGRADES to
61
- * unserialized rather than blocking boot forever — the DDL is still individually idempotent). */
62
- export declare function acquireEnsureSchemaLock(conn: PoolConnection, tag?: string): Promise<boolean>;
61
+ * rest sleeping (not blocked in-DB). Polls until acquired (7.83.0: never degrades to unserialized — the S-287
62
+ * `ADD INDEX` leg is not race-safe); a connection whose probe keeps throwing surfaces as a boot failure. */
63
+ export declare function acquireEnsureSchemaLock(conn: PoolConnection, tag?: string): Promise<void>;
63
64
  /** Release {@link ENSURE_SCHEMA_LOCK} on `conn` (best-effort — the lock also auto-frees when the connection closes). */
64
65
  export declare function releaseEnsureSchemaLock(conn: PoolConnection, tag?: string): Promise<void>;
66
+ /**
67
+ * S-287:`SCHEMA_STATEMENTS` 建的那批表**在存量库上可能缺的索引**(声明与 PG 侧逐条共用同一份 —— 见
68
+ * `plugins/ensure-index.ts` 头注与 `plugins/schema-indexes.ts`)。
69
+ *
70
+ * 组合口径与 `SCHEMA_STATEMENTS` **一一对应**:凡是它建的表,索引声明就进这个数组;它不建的表
71
+ * (device / roster / background-agent / mailbox / task-attachment / memory 两族……由 `boot/stores.ts`
72
+ * 各自的 `ensureTiDB*Schema` 腿建)由那条腿自己应用自己的声明 —— 否则这里会对一张还不存在的表发 ALTER。
73
+ *
74
+ * 新建库上这批索引早已随 `CREATE TABLE` 的内联 `KEY` 到货 ⇒ `ensureIndex` 的探测全部命中、**零 DDL**。
75
+ */
76
+ export declare const SCHEMA_INDEXES: readonly IndexSpec[];
65
77
  /** Create tables if absent (+ seed the image-bake admission sentinel). Safe to call on every startup.
66
78
  *
67
79
  * Per the SCHEMA POLICY on {@link SCHEMA_STATEMENTS} this is a pure CREATE run — there are NO additive
@@ -6,6 +6,21 @@ import { TIDB_LEADER_RUN_STATEMENTS } from "./leader-run-store-sql.js";
6
6
  import { TIDB_ADOPTION_LOG_STATEMENTS } from "./adoption-log-sql.js";
7
7
  import { TIDB_PERMISSION_RULE_STATEMENTS } from "./permission-rule-store-sql.js";
8
8
  import { TIDB_RETENTION_STATEMENTS } from "./retention-store-sql.js";
9
+ import { ensureIndexes } from "./ensure-index.js";
10
+ import { CENTRAL_SCHEMA_INDEXES } from "./schema-indexes.js";
11
+ import { SESSION_INDEXES } from "./pg-session-storage.js";
12
+ import { TOOL_RESULT_INDEXES } from "./tool-result-store-sql.js";
13
+ import { COST_QUOTA_INDEXES } from "./pg-cost-quota.js";
14
+ import { RATE_LIMIT_INDEXES } from "./pg-rate-limiter.js";
15
+ import { OUTCOME_LEDGER_INDEXES } from "./outcome-ledger-sql.js";
16
+ import { IMAGE_INDEX_INDEXES } from "./image-index-sql.js";
17
+ import { IMAGE_BAKE_INDEXES } from "./image-bake-store-sql.js";
18
+ import { APPROVAL_ASK_INDEXES } from "./approval-ask-store-sql.js";
19
+ import { ADOPTION_LOG_INDEXES } from "./adoption-log-sql.js";
20
+ import { PERMISSION_RULE_INDEXES } from "./permission-rule-store-sql.js";
21
+ import { RETENTION_INDEXES } from "./retention-store-sql.js";
22
+ import { LEADER_RUN_INDEXES } from "./leader-run-store-sql.js";
23
+ import { pollUntilLocked } from "./ensure-schema-lock-policy.js";
9
24
  export function tidbPoolOptions(tidb) {
10
25
  const { host, port, user, password, database, connectionLimit } = tidb;
11
26
  const limit = connectionLimit ?? 10;
@@ -670,20 +685,10 @@ export const SCHEMA_STATEMENTS = [
670
685
  ];
671
686
  export const ENSURE_SCHEMA_LOCK = "sema_ensure_schema";
672
687
  export async function acquireEnsureSchemaLock(conn, tag = "ensureSchema") {
673
- await new Promise((r) => setTimeout(r, Math.floor(Math.random() * 400)));
674
- for (let attempt = 0; attempt < 40; attempt++) {
675
- try {
676
- const [rows] = await conn.query("SELECT GET_LOCK(?, 0) AS got", [ENSURE_SCHEMA_LOCK]);
677
- if (Number(rows[0]?.got) === 1)
678
- return true;
679
- }
680
- catch (err) {
681
- console.warn(`[${tag}] GET_LOCK('${ENSURE_SCHEMA_LOCK}') attempt ${attempt + 1}/40:`, err?.message ?? err);
682
- }
683
- await new Promise((r) => setTimeout(r, 100 + Math.min(attempt, 3) * 100 + Math.floor(Math.random() * 150)));
684
- }
685
- console.warn(`[${tag}] could not acquire '${ENSURE_SCHEMA_LOCK}' after retries`);
686
- return false;
688
+ await pollUntilLocked(async () => {
689
+ const [rows] = await conn.query("SELECT GET_LOCK(?, 0) AS got", [ENSURE_SCHEMA_LOCK]);
690
+ return Number(rows[0]?.got) === 1;
691
+ }, { tag, label: `GET_LOCK('${ENSURE_SCHEMA_LOCK}')` });
687
692
  }
688
693
  export async function releaseEnsureSchemaLock(conn, tag = "ensureSchema") {
689
694
  try {
@@ -693,14 +698,32 @@ export async function releaseEnsureSchemaLock(conn, tag = "ensureSchema") {
693
698
  console.warn(`[${tag}] RELEASE_LOCK('${ENSURE_SCHEMA_LOCK}') failed (lock auto-frees on connection close):`, err);
694
699
  }
695
700
  }
701
+ export const SCHEMA_INDEXES = [
702
+ ...CENTRAL_SCHEMA_INDEXES,
703
+ ...SESSION_INDEXES,
704
+ ...TOOL_RESULT_INDEXES,
705
+ ...COST_QUOTA_INDEXES,
706
+ ...RATE_LIMIT_INDEXES,
707
+ ...OUTCOME_LEDGER_INDEXES,
708
+ ...IMAGE_INDEX_INDEXES,
709
+ ...IMAGE_BAKE_INDEXES,
710
+ ...APPROVAL_ASK_INDEXES,
711
+ ...ADOPTION_LOG_INDEXES,
712
+ ...PERMISSION_RULE_INDEXES,
713
+ ...RETENTION_INDEXES,
714
+ ...LEADER_RUN_INDEXES,
715
+ ];
696
716
  export async function ensureSchema(pool) {
697
717
  const conn = await pool.getConnection();
698
- const locked = await acquireEnsureSchemaLock(conn);
718
+ let locked = false;
699
719
  try {
720
+ await acquireEnsureSchemaLock(conn);
721
+ locked = true;
700
722
  for (const stmt of SCHEMA_STATEMENTS) {
701
723
  await conn.query(stmt);
702
724
  }
703
725
  await conn.query("INSERT IGNORE INTO image_bake_admit (pool) VALUES ('standard')");
726
+ await ensureIndexes((text, params) => conn.query(text, params), "mysql", SCHEMA_INDEXES);
704
727
  }
705
728
  finally {
706
729
  if (locked)
@@ -2,10 +2,13 @@ import type { ToolResultProvenance, ToolResultStore, ToolResultSlice, ToolResult
2
2
  import type { Pool as MySqlPool } from "mysql2/promise";
3
3
  import type { Pool as PgPool, PoolClient as PgPoolClient } from "pg";
4
4
  import { type SqlDriver } from "./sql-driver.js";
5
+ import { type IndexSpec } from "./ensure-index.js";
5
6
  /** PG schema for the tool_result table — the PG translation of tidb-pool.ts's tool_result DDL
6
7
  * (LONGTEXT→TEXT, DATETIME(3)→TIMESTAMPTZ(3), inline KEY→separate CREATE INDEX). Disjoint from other stores'
7
8
  * tables, so a self-contained ensureSchema is safe (central pg-pool aggregation is done separately). */
8
9
  export declare const PG_TOOL_RESULT_SCHEMA: string[];
10
+ /** S-287:本 store 的索引**声明**(两方言共用一份)。PG 侧由下面的 `ensureSchema` 应用,MySQL 侧由 `tidb-pool.ts` 的中央 `ensureSchema` 应用(那里内联 `KEY` 已在 `CREATE TABLE` 里 ⇒ 新建库探到即零 DDL,存量库缺谁补谁)。加索引以外的 schema 变更仍归运维,见 `plugins/ensure-index.ts` 头注。 */
11
+ export declare const TOOL_RESULT_INDEXES: readonly IndexSpec[];
9
12
  /** Idempotent schema apply for the tool_result table (for the integration test to call). */
10
13
  export declare function ensureSchema(pool: PgPool | PgPoolClient): Promise<void>;
11
14
  /**
@@ -2,6 +2,7 @@ import { MAX_MINTED_TOOL_RESULT_REF_CHARS, assertSafeToolResultRef, assertToolRe
2
2
  import { pgSanitizeText } from "./pg-safe-json.js";
3
3
  import { mysqlDriver, pgDriver } from "./sql-driver.js";
4
4
  import { MANAGED_RETENTION } from "./retention-store-sql.js";
5
+ import { ensureIndexes } from "./ensure-index.js";
5
6
  export const PG_TOOL_RESULT_SCHEMA = [
6
7
  `CREATE TABLE IF NOT EXISTS tool_result (
7
8
  ref VARCHAR(518) COLLATE "C" NOT NULL,
@@ -11,11 +12,14 @@ export const PG_TOOL_RESULT_SCHEMA = [
11
12
  created_at TIMESTAMPTZ(3) NOT NULL,
12
13
  PRIMARY KEY (ref)
13
14
  )`,
14
- `CREATE INDEX IF NOT EXISTS idx_tool_result_created ON tool_result (created_at)`,
15
+ ];
16
+ export const TOOL_RESULT_INDEXES = [
17
+ { table: "tool_result", name: "idx_tool_result_created", columns: ["created_at"] },
15
18
  ];
16
19
  export async function ensureSchema(pool) {
17
20
  for (const stmt of PG_TOOL_RESULT_SCHEMA)
18
21
  await pool.query(stmt);
22
+ await ensureIndexes((t, p) => pool.query(t, p), "pg", TOOL_RESULT_INDEXES);
19
23
  }
20
24
  export async function assertToolResultProvenanceSchema(query, dialect) {
21
25
  const widthRow = await query(dialect === "tidb"
@@ -190,7 +190,8 @@ export declare function screenedStoredEventData(type: string, data: unknown): un
190
190
  /** `text_end` 段末帧的**唯一**铸点(三腿共用:top stream / 转发子代腿 / 子代 tail 面)。content = 段权威全文 ⇒ 与
191
191
  * durable 面(`result` / 账本 `text` 行)同一只 {@link redactModelText}(认出才改写、抛则占位、不设上限)。
192
192
  * 此前三处各自逐字透传 —— 同一份文本毫秒后在 `done.result.result` 上已脱,live 面却在凭据生成瞬间明文(B-114)。
193
- * `text_delta` 仍逐字:跨 chunk 的凭据无法就地判,流式脱敏是独立设计件(S-270)。
193
+ * `text_delta` 仍逐字:跨 chunk 的凭据无法就地判;clay [ref] ②(2026-09-18)裁定**维持逐字成文**(S-270 U-3 关票),
194
+ * 权威段 `text_end.content` 已脱敏、消费端段末整段替换即得脱敏读法。
194
195
  * 坏形(content 非串/空串)⇒ null(丢帧,不铸「权威空段」:core 契约明言空段不发本帧,消费端收到空段会清掉已攒 delta)。
195
196
  * 身份**四键**随行(live 现状带全四键,消费端可能已依赖);值经 {@link identityKey} —— 非空 string 才上 wire
196
197
  * (S-334 起不再逐字透传:坏形身份键会在 live 写口上铸出假游标)。 */
@@ -77,6 +77,12 @@ export declare function resetPpkScanBytesForTest(): void;
77
77
  * (亲读 `@sema-agent/core/dist/agents/subagent-steps.js:9-11`),截过与天生就短在 wire 上不可区分。
78
78
  * 所以一个 `arm="fragment"` 计数可能来自残片,也可能来自一个恰好落在阈值之上的 look-alike;
79
79
  * core [ref] 落地后这一支**趋零是证据、不归零不是证明**。别把它当截断事实的度量用。 */
80
+ /**
81
+ * 🔴 **词名 = 表归属,不是语义**(clay 裁 [ref] ①,2026-09-18,关 S-307):`"full"` = 强证据表(`SECRET_PATTERNS` 一族,
82
+ * 含 7.76.2 起改判进来的 PEM/ppk 体)命中的臂,`"fragment"` = 弱证据表({@link FRAGMENT_SECRET_PATTERNS})命中的臂。
83
+ * 7.76.2 起两档语义已是「强证据 / 弱证据」,词名**刻意保留**:它是 Prometheus 标签 `redactions_applied_total{arm}` 的
84
+ * 标签值,改名 = 硬 breaking 的标签值漂移(面板与告警按值匹配),而语义只在这一段注释里说全即可。判据是 {@link armOfToken}。
85
+ */
80
86
  export type RedactionArm = "full" | "fragment";
81
87
  export interface RedactionHitMeta {
82
88
  /** 命中臂的**判别力档位**(闭集两词,S-303):`"fragment"` = {@link FRAGMENT_SECRET_PATTERNS} 那一族
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/server",
3
- "version": "7.82.1",
3
+ "version": "7.83.0",
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",