@sema-agent/server 7.29.0 → 7.30.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 (52) hide show
  1. package/USAGE.md +20 -5
  2. package/dist/boot/governance-seams.d.ts +13 -0
  3. package/dist/boot/governance-seams.js +21 -1
  4. package/dist/boot/retention-lane.d.ts +206 -0
  5. package/dist/boot/retention-lane.js +279 -0
  6. package/dist/boot/shutdown.d.ts +8 -0
  7. package/dist/boot/shutdown.js +21 -2
  8. package/dist/config-types.d.ts +22 -1
  9. package/dist/config-types.js +6 -1
  10. package/dist/config.d.ts +15 -1
  11. package/dist/config.js +43 -2
  12. package/dist/http/routes/capabilities.js +30 -0
  13. package/dist/http/routes/memory-policy.d.ts +13 -0
  14. package/dist/http/routes/memory-policy.js +79 -2
  15. package/dist/http/routes/retention-ops.d.ts +36 -0
  16. package/dist/http/routes/retention-ops.js +190 -0
  17. package/dist/http/server.js +14 -0
  18. package/dist/main.js +74 -0
  19. package/dist/memory-scope.d.ts +5 -3
  20. package/dist/memory-scope.js +6 -8
  21. package/dist/observability/fail-open.d.ts +4 -0
  22. package/dist/observability/fail-open.js +4 -0
  23. package/dist/plugins/caching-session-store.d.ts +11 -1
  24. package/dist/plugins/caching-session-store.js +13 -0
  25. package/dist/plugins/checkpoint-store-sql.d.ts +3 -0
  26. package/dist/plugins/checkpoint-store-sql.js +4 -0
  27. package/dist/plugins/local-checkpoint-store.d.ts +3 -0
  28. package/dist/plugins/local-checkpoint-store.js +4 -0
  29. package/dist/plugins/local-session-store.d.ts +5 -0
  30. package/dist/plugins/local-session-store.js +6 -0
  31. package/dist/plugins/memory-engine-pg.js +22 -10
  32. package/dist/plugins/memory-engine-tidb.js +22 -11
  33. package/dist/plugins/memory-key-guards.d.ts +27 -4
  34. package/dist/plugins/memory-key-guards.js +57 -6
  35. package/dist/plugins/memory-sync-store-pg.js +5 -0
  36. package/dist/plugins/memory-sync-store-tidb.js +5 -0
  37. package/dist/plugins/pg-pool.js +4 -0
  38. package/dist/plugins/pg-session-storage.d.ts +2 -0
  39. package/dist/plugins/pg-session-storage.js +3 -0
  40. package/dist/plugins/retention-lane-store-sql.d.ts +254 -0
  41. package/dist/plugins/retention-lane-store-sql.js +236 -0
  42. package/dist/plugins/retention-store-sql.d.ts +468 -0
  43. package/dist/plugins/retention-store-sql.js +793 -0
  44. package/dist/plugins/store-backend.d.ts +20 -0
  45. package/dist/plugins/store-backend.js +7 -0
  46. package/dist/plugins/tidb-pool.js +5 -0
  47. package/dist/plugins/tidb-session-store.d.ts +3 -0
  48. package/dist/plugins/tidb-session-store.js +4 -0
  49. package/dist/plugins/tool-result-store-sql.d.ts +3 -0
  50. package/dist/plugins/tool-result-store-sql.js +4 -0
  51. package/dist/run-local.js +16 -0
  52. package/package.json +1 -1
@@ -25,6 +25,8 @@ import type { CounterDegradeHook } from "./write-behind-counter.js";
25
25
  import { PgRateLimiter } from "./pg-rate-limiter.js";
26
26
  import { type SqlSharedMemoryStore, type SharedMemoryScopeAuthorizer } from "./shared-memory-store-sql.js";
27
27
  import { type AdoptionLogStore } from "./adoption-log-sql.js";
28
+ import { type SqlRetentionStore, type SqlRetentionStoreOptions } from "./retention-store-sql.js";
29
+ import { type RetentionLaneStore } from "./retention-lane-store-sql.js";
28
30
  import type { PermissionRuleStoreBundle } from "../rules-consent.js";
29
31
  export type RunStore = TiDBRunStore | PgRunStore | FileRunStore;
30
32
  /** E18 resume-at eventId→entryId anchor map — tidb/pg/local 3-backend (works LOCAL; needs only the session tree +
@@ -207,6 +209,24 @@ export interface StoreBackend {
207
209
  * 缺席 ⇒ endpoint 落到显式的单副本内存降级臂(见 `leader/endpoint.ts` 的 store 缺席注)。
208
210
  */
209
211
  leaderRun?(): LeaderRunStore;
212
+ /**
213
+ * #270 —— 托管留存的**破坏性**三方法(core `ManagedRetentionCapability` 的 server 侧真身)。
214
+ * **SQL 后端专有**,`local` 刻意省略:那三条腿是跨十余张表的单事务级联,file/in-memory 形没有事务面
215
+ * 也没有那些表,所以它诚实声明 `retention:"none"`(见 `local-session-store.ts` 的同款注)。
216
+ *
217
+ * `taskAttachmentTable` 必填、无默认值 —— boot 只在配了对象存储时才 ensure 那张表,一条盲发的
218
+ * DELETE 在无 MinIO 的部署上会以 unknown-table 打红整轮 sweep(理由逐字见
219
+ * `retention-store-sql.ts` 的 `SqlRetentionStoreOptions`)。
220
+ */
221
+ retention?(opts: SqlRetentionStoreOptions): SqlRetentionStore;
222
+ /**
223
+ * #270 车2 —— 留存执行面的**非破坏性**半场:sweep 租约、legal-hold 的放置/解除、审计表的读与
224
+ * 非破坏行的写。同样 SQL 专有(它写的三张表只在 SQL schema 里)。
225
+ *
226
+ * 🔴 与上一格**分家**是有意的:拿到本对象的消费方(operator 路由)结构上删不掉任何业务数据。
227
+ * 两面合并会让「拿到这只店 = 能删」这条读法失真。
228
+ */
229
+ retentionLane?(): RetentionLaneStore;
210
230
  breaker?(onWriteFail?: (streak: number) => void): BreakerStateStore;
211
231
  costQuota?(limitMicroUsd: number, windowMs: number, onDegraded?: CounterDegradeHook): CostQuotaStore;
212
232
  rateLimiter?(limit: number, onDegraded?: CounterDegradeHook): RateLimiterStore;
@@ -43,6 +43,9 @@ import { TiDBSessionStore } from "./tidb-session-store.js";
43
43
  import { PgSessionStore } from "./pg-session-storage.js";
44
44
  import { TiDBSharedMemoryStore, PgSharedMemoryStore } from "./shared-memory-store-sql.js";
45
45
  import { TiDBAdoptionLogStore, PgAdoptionLogStore } from "./adoption-log-sql.js";
46
+ // #270:托管留存的两半场(破坏性三方法 = 车1;租约/hold/审计 = 车2)。SQL 后端专有,local 诚实缺席。
47
+ import { TiDBRetentionStore, PgRetentionStore } from "./retention-store-sql.js";
48
+ import { TiDBRetentionLaneStore, PgRetentionLaneStore } from "./retention-lane-store-sql.js";
46
49
  // #154 车二:持久化权限规则店(三面一束)。`mysqlDriver`/`pgDriver` 是既有的方言中立 seam。
47
50
  // #203 §1:local 车道的 File 三面束(core 现成 provider + 本仓 File 形审批记录/导入票)。
48
51
  import { createSqlPermissionRuleStores } from "./permission-rule-store-sql.js";
@@ -120,6 +123,8 @@ class TiDBBackend {
120
123
  imageIndex() { return new TiDBImageIndex(this.pool); }
121
124
  imageBake() { return new TiDBImageBake(this.pool); }
122
125
  leaderRun() { return new TiDBLeaderRunStore(this.pool); } // #193 车4 件1(无状态 store,每次新建同兄弟)
126
+ retention(opts) { return new TiDBRetentionStore(this.pool, opts); } // #270 车1(破坏性三方法)
127
+ retentionLane() { return new TiDBRetentionLaneStore(this.pool); } // #270 车2(租约/hold/审计,删不了业务数据)
123
128
  breaker(onWriteFail) { return new TiDBBreakerState(this.pool, onWriteFail); }
124
129
  costQuota(limitMicroUsd, windowMs, onDegraded) { return new TiDBCostQuota(this.pool, limitMicroUsd, windowMs, undefined, onDegraded, this.config.dbQueryTimeoutMs); }
125
130
  rateLimiter(limit, onDegraded) { return new TiDBRateLimiter(this.pool, limit, undefined, undefined, onDegraded, this.config.dbQueryTimeoutMs); }
@@ -158,6 +163,8 @@ class PgBackend {
158
163
  imageIndex() { return new PgImageIndex(this.pool); }
159
164
  imageBake() { return new PgImageBake(this.pool); }
160
165
  leaderRun() { return new PgLeaderRunStore(this.pool); } // #193 车4 件1(SQL twin)
166
+ retention(opts) { return new PgRetentionStore(this.pool, opts); } // #270 车1(SQL twin)
167
+ retentionLane() { return new PgRetentionLaneStore(this.pool); } // #270 车2(SQL twin)
161
168
  breaker(onWriteFail) { return new PgBreakerState(this.pool, onWriteFail); }
162
169
  costQuota(limitMicroUsd, windowMs, onDegraded) { return new PgCostQuota(this.pool, limitMicroUsd, windowMs, undefined, onDegraded, this.config.dbQueryTimeoutMs); }
163
170
  rateLimiter(limit, onDegraded) { return new PgRateLimiter(this.pool, limit, undefined, undefined, onDegraded, this.config.dbQueryTimeoutMs); }
@@ -3,6 +3,7 @@ import { TIDB_APPROVAL_ASK_STATEMENTS } from "./approval-ask-store-sql.js";
3
3
  import { TIDB_LEADER_RUN_STATEMENTS } from "./leader-run-store-sql.js";
4
4
  import { TIDB_ADOPTION_LOG_STATEMENTS } from "./adoption-log-sql.js";
5
5
  import { TIDB_PERMISSION_RULE_STATEMENTS } from "./permission-rule-store-sql.js";
6
+ import { TIDB_RETENTION_STATEMENTS } from "./retention-store-sql.js";
6
7
  /**
7
8
  * Shared TiDB (MySQL wire-compatible) connection pool for the durable Session center (L1).
8
9
  * Owned by `main.ts`; closed on shutdown.
@@ -715,6 +716,10 @@ export const SCHEMA_STATEMENTS = [
715
716
  // permission-rule-store-sql.ts 的 `TIDB_PERMISSION_RULE_STATEMENTS`(与 PG twin 并排);展开进这个
716
717
  // 数组的理由与上面那族逐字相同(named-lock 的那条 conn + 「这张表算生产 schema」的声明)。
717
718
  ...TIDB_PERMISSION_RULE_STATEMENTS,
719
+ // #270 车1(托管留存执行面)的四张表:审计(§6)/ hold(§5)/ sweep 租约(§3)/ 墓碑(§2)。真源 =
720
+ // retention-store-sql.ts 的 `TIDB_RETENTION_STATEMENTS`(与 PG twin 并排);展开进这个数组的理由与
721
+ // 上面那几族逐字相同(named-lock 的那条 conn + 「这张表算生产 schema」的声明)。
722
+ ...TIDB_RETENTION_STATEMENTS,
718
723
  ];
719
724
  /** Named MySQL/TiDB advisory lock that serializes the whole `ensureSchema` DDL run (see below). */
720
725
  export const ENSURE_SCHEMA_LOCK = "sema_ensure_schema";
@@ -16,6 +16,9 @@ import type { SessionSummary } from "./store-contracts.js";
16
16
  import { type StagingHandle } from "../session-sync-kernel.js";
17
17
  export declare class TiDBSessionStore implements SessionStore {
18
18
  private readonly pool;
19
+ /** #270 车1:托管留存声明。读法与「为什么 SQL 店答 managed 而实现体在别处」逐字见
20
+ * `retention-store-sql.ts` 的 {@link MANAGED_RETENTION}。 */
21
+ readonly retention: import("@sema-agent/core").RetentionDeclaration;
19
22
  /** In-flight acquisitions keyed by id, so concurrent acquire(sameId) in one process share one. */
20
23
  private readonly pending;
21
24
  constructor(pool: Pool);
@@ -14,11 +14,15 @@
14
14
  import { StoredSession, SessionError, uuidv7, validateEntriesForImport, leafIdAfterEntry } from "@sema-agent/core";
15
15
  import { TiDBSessionStorage } from "./tidb-session-storage.js";
16
16
  import { escapeLike } from "./sql-escape.js";
17
+ import { MANAGED_RETENTION } from "./retention-store-sql.js";
17
18
  import { contentForkRelation, fastForwardSharedContentDiverged } from "../session-sync-content.js";
18
19
  import { classifySyncRelationshipByIds, SyncConflictError, stagingIdFor, STAGING_ID_MARKER, STAGING_GC_GRACE_MS, // 两孪生店同源(理由见 kernel 处顶注:同值双抄单边改值 ⇒ 两后端 GC 判定分家)
19
20
  } from "../session-sync-kernel.js";
20
21
  export class TiDBSessionStore {
21
22
  pool;
23
+ /** #270 车1:托管留存声明。读法与「为什么 SQL 店答 managed 而实现体在别处」逐字见
24
+ * `retention-store-sql.ts` 的 {@link MANAGED_RETENTION}。 */
25
+ retention = MANAGED_RETENTION;
22
26
  /** In-flight acquisitions keyed by id, so concurrent acquire(sameId) in one process share one. */
23
27
  pending = new Map();
24
28
  constructor(pool) {
@@ -26,6 +26,9 @@ export declare function assertToolResultProvenanceSchema(query: (sql: string) =>
26
26
  /** Dual-dialect durable ToolResultStore. See the file header for the dialect-delta ledger. */
27
27
  export declare class SqlToolResultStore implements ToolResultStore {
28
28
  protected readonly db: SqlDriver;
29
+ /** #270 车1:托管留存声明。读法与「为什么 SQL 店答 managed 而三方法的实现体在 `retention-store-sql.ts`」
30
+ * 逐字见 {@link MANAGED_RETENTION}(本店的 `tool_result` 行由那只聚合店按期清:随会话树删 + 孤儿腿)。 */
31
+ readonly retention: import("@sema-agent/core").RetentionDeclaration;
29
32
  constructor(db: SqlDriver);
30
33
  /** Pick the dialect's SQL text. Both statements stay written out at the call site ON PURPOSE. */
31
34
  private q;
@@ -38,6 +38,7 @@
38
38
  import { MAX_MINTED_TOOL_RESULT_REF_CHARS, assertSafeToolResultRef, assertToolResultProvenanceMatch, normalizeToolResultProvenance } from "@sema-agent/core";
39
39
  import { pgSanitizeText } from "./pg-safe-json.js";
40
40
  import { mysqlDriver, pgDriver } from "./sql-driver.js";
41
+ import { MANAGED_RETENTION } from "./retention-store-sql.js";
41
42
  /** PG schema for the tool_result table — the PG translation of tidb-pool.ts's tool_result DDL
42
43
  * (LONGTEXT→TEXT, DATETIME(3)→TIMESTAMPTZ(3), inline KEY→separate CREATE INDEX). Disjoint from other stores'
43
44
  * tables, so a self-contained ensureSchema is safe (central pg-pool aggregation is done separately). */
@@ -105,6 +106,9 @@ export async function assertToolResultProvenanceSchema(query, dialect) {
105
106
  /** Dual-dialect durable ToolResultStore. See the file header for the dialect-delta ledger. */
106
107
  export class SqlToolResultStore {
107
108
  db;
109
+ /** #270 车1:托管留存声明。读法与「为什么 SQL 店答 managed 而三方法的实现体在 `retention-store-sql.ts`」
110
+ * 逐字见 {@link MANAGED_RETENTION}(本店的 `tool_result` 行由那只聚合店按期清:随会话树删 + 孤儿腿)。 */
111
+ retention = MANAGED_RETENTION;
108
112
  constructor(db) {
109
113
  this.db = db;
110
114
  }
package/dist/run-local.js CHANGED
@@ -73,6 +73,7 @@ import { createMemorySyncRunner, createMemorySyncTransport } from "./memory-sync
73
73
  import { buildPricing, cappedCeiling, createTracer } from "./budget.js";
74
74
  import { createSharedRunnerDeps } from "./boot/runner-deps.js";
75
75
  import { createGovernanceSeams } from "./boot/governance-seams.js";
76
+ import { assertRetentionLaneWirable } from "./boot/retention-lane.js"; // #270 车2:lane 自持门(本地形恒无执行器)
76
77
  import { createOrgMemoryAdmissionWiring } from "./boot/org-memory.js";
77
78
  import { createPermissionDeniedMeter } from "./observability/tool-trace.js";
78
79
  import { createKeyResolver } from "./key-resolver.js";
@@ -607,6 +608,21 @@ export async function runLocal(argv, deps = {}) {
607
608
  // 有:`COMPLIANCE_PROFILE` / `LOCKED_CONFIG_KEYS` / `RETENTION_MAX_AGE_DAYS` 是从同一份本地 `.env` 读出来
608
609
  // 的,一个写下了档位的用户在 `sema` 与本机 HTTP 服务上必须得到同一个答案(两条腿对同一份配置两套行为
609
610
  // 正是本仓在册的病族)。三键未配 = 三座席缺席 = 本腿逐字零变化。
611
+ // #270 车2:lane 自持门在本地形也要跑,理由与上一段逐字相同 —— `RETENTION_SWEEP_INTERVAL_SEC>0`
612
+ // 是从同一份 `.env` 读出来的,而本地形**结构上**没有执行器(file 店三方法不存在,诚实声明 "none")。
613
+ // 少了这道门,一个写下了那根旋钮的用户会在 `sema` 上得到一台自称有留存治理、其实什么都不删的机器,
614
+ // 而在 HTTP 形上得到一条拒启 —— 两条腿对同一份配置两套行为,正是本仓在册的病族。
615
+ assertRetentionLaneWirable({
616
+ intervalSec: config.retentionSweep.intervalSec,
617
+ policy: config.retentionPolicy,
618
+ executor: undefined, // 本地形恒无执行器(见上)
619
+ stores: [
620
+ { name: "sessionStore", store: sessionStore },
621
+ { name: "checkpointStore", store: fileBackend.checkpointStore },
622
+ { name: "toolResultStore", store: fileBackend.toolResultStore },
623
+ ],
624
+ locked: (config.lockedConfigKeys ?? []).includes("retentionPolicy"),
625
+ });
610
626
  const governanceSeams = createGovernanceSeams({
611
627
  config,
612
628
  logger,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/server",
3
- "version": "7.29.0",
3
+ "version": "7.30.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",