@sema-agent/server 7.82.0 → 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 (89) hide show
  1. package/USAGE.md +17 -14
  2. package/dist/bench/s1/arms.d.ts +4 -4
  3. package/dist/bench/s1/arms.js +1 -2
  4. package/dist/bench/s1/live-deps.js +0 -1
  5. package/dist/bench/s1/runner-ctx.d.ts +3 -3
  6. package/dist/bench/s1/tasks.d.ts +8 -4
  7. package/dist/boot/stage-07-capability-layer.d.ts +1 -0
  8. package/dist/boot/stage-07-capability-layer.js +1 -1
  9. package/dist/boot/stage-08-reapers.d.ts +1 -0
  10. package/dist/boot/stage-09-leader.d.ts +1 -0
  11. package/dist/boot/stage-10-http-server.d.ts +1 -0
  12. package/dist/boot/stage-10-http-server.js +2 -1
  13. package/dist/config-catalog.js +2 -3
  14. package/dist/config.js +1 -0
  15. package/dist/http/routes/capabilities.js +2 -0
  16. package/dist/http/server.d.ts +8 -0
  17. package/dist/leader/endpoint.js +2 -0
  18. package/dist/leader/leader.d.ts +33 -6
  19. package/dist/leader/leader.js +54 -45
  20. package/dist/leader/merge.d.ts +38 -29
  21. package/dist/leader/merge.js +45 -38
  22. package/dist/leader/wire.d.ts +2 -17
  23. package/dist/leader/wire.js +5 -58
  24. package/dist/observability/fail-open.d.ts +5 -5
  25. package/dist/observability/fail-open.js +5 -2
  26. package/dist/observability/run-terminal-log.d.ts +0 -7
  27. package/dist/observability/run-terminal-log.js +9 -20
  28. package/dist/plugins/adoption-log-sql.d.ts +3 -0
  29. package/dist/plugins/adoption-log-sql.js +5 -1
  30. package/dist/plugins/approval-ask-store-sql.d.ts +3 -0
  31. package/dist/plugins/approval-ask-store-sql.js +9 -5
  32. package/dist/plugins/background-agent-store-sql.d.ts +3 -0
  33. package/dist/plugins/background-agent-store-sql.js +7 -2
  34. package/dist/plugins/device-store-sql.d.ts +3 -0
  35. package/dist/plugins/device-store-sql.js +9 -4
  36. package/dist/plugins/ensure-index.d.ts +42 -0
  37. package/dist/plugins/ensure-index.js +81 -0
  38. package/dist/plugins/ensure-schema-lock-policy.d.ts +29 -0
  39. package/dist/plugins/ensure-schema-lock-policy.js +31 -0
  40. package/dist/plugins/image-bake-store-sql.d.ts +3 -0
  41. package/dist/plugins/image-bake-store-sql.js +6 -2
  42. package/dist/plugins/image-index-sql.d.ts +3 -0
  43. package/dist/plugins/image-index-sql.js +8 -4
  44. package/dist/plugins/leader-run-store-sql.d.ts +3 -0
  45. package/dist/plugins/leader-run-store-sql.js +6 -2
  46. package/dist/plugins/mailbox-store-sql.d.ts +3 -0
  47. package/dist/plugins/mailbox-store-sql.js +6 -1
  48. package/dist/plugins/memory-engine-pg.d.ts +4 -0
  49. package/dist/plugins/memory-engine-pg.js +6 -6
  50. package/dist/plugins/memory-engine-tidb.js +5 -0
  51. package/dist/plugins/memory-sync-store-pg.d.ts +5 -0
  52. package/dist/plugins/memory-sync-store-pg.js +9 -2
  53. package/dist/plugins/memory-sync-store-tidb.js +6 -0
  54. package/dist/plugins/one-time-migrations.d.ts +1 -1
  55. package/dist/plugins/one-time-migrations.js +7 -14
  56. package/dist/plugins/outcome-ledger-sql.d.ts +3 -0
  57. package/dist/plugins/outcome-ledger-sql.js +7 -3
  58. package/dist/plugins/permission-rule-store-sql.d.ts +3 -0
  59. package/dist/plugins/permission-rule-store-sql.js +9 -5
  60. package/dist/plugins/pg-cost-quota.d.ts +3 -0
  61. package/dist/plugins/pg-cost-quota.js +5 -1
  62. package/dist/plugins/pg-pool.d.ts +23 -2
  63. package/dist/plugins/pg-pool.js +22 -37
  64. package/dist/plugins/pg-rate-limiter.d.ts +3 -0
  65. package/dist/plugins/pg-rate-limiter.js +5 -1
  66. package/dist/plugins/pg-session-storage.d.ts +3 -0
  67. package/dist/plugins/pg-session-storage.js +8 -4
  68. package/dist/plugins/remote-env-adb.d.ts +62 -3
  69. package/dist/plugins/remote-env-adb.js +27 -15
  70. package/dist/plugins/remote-env-host.js +1 -1
  71. package/dist/plugins/remote-shell.d.ts +7 -11
  72. package/dist/plugins/remote-shell.js +3 -3
  73. package/dist/plugins/retention-store-sql.d.ts +3 -0
  74. package/dist/plugins/retention-store-sql.js +7 -3
  75. package/dist/plugins/roster-store-sql.d.ts +3 -0
  76. package/dist/plugins/roster-store-sql.js +6 -1
  77. package/dist/plugins/schema-indexes.d.ts +21 -0
  78. package/dist/plugins/schema-indexes.js +25 -0
  79. package/dist/plugins/task-attachment-store.d.ts +3 -0
  80. package/dist/plugins/task-attachment-store.js +7 -2
  81. package/dist/plugins/tidb-pool.d.ts +15 -3
  82. package/dist/plugins/tidb-pool.js +38 -15
  83. package/dist/plugins/tool-result-store-sql.d.ts +3 -0
  84. package/dist/plugins/tool-result-store-sql.js +5 -1
  85. package/dist/plugins/web-search.d.ts +50 -2
  86. package/dist/plugins/web-search.js +9 -2
  87. package/dist/trace/project.d.ts +2 -1
  88. package/dist/trace/redact.d.ts +6 -0
  89. package/package.json +2 -2
@@ -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"
@@ -52,8 +52,56 @@
52
52
  * 验证搜索配对不对。挂哪儿(boot 期一次性 warn / `/health` 子字段 / 显式端点)未定 ——
53
53
  * 注意 boot 期探活会给每次启动加一次出网,多租/离线部署要能关。
54
54
  */
55
- /** Search providers this backend speaks. Absent `WEB_SEARCH_PROVIDER` ⇒ no backend ⇒ WebSearch is not assembled. */
56
- export type WebSearchProvider = "brave" | "tavily" | "searxng";
55
+ /**
56
+ * Search providers this backend speaks —— **词表的唯一属主**(运行期与类型同一份)。
57
+ * Absent `WEB_SEARCH_PROVIDER` ⇒ no backend ⇒ WebSearch is not assembled.
58
+ *
59
+ * 🔴 **为什么是常量元组而不是裸 union**(车GW 对抗复审 F1[medium],2026-09-17):改前这张表在仓里有**四份**
60
+ * —— 类型一份 + 两只解析器各一条 `provider !== "brave" && …` 后置链 + `config-catalog` 的
61
+ * `enumValues: [...]` 字面量(那个字段是 `readonly string[]`,与本类型零类型联系)。加一只后端时 tsc
62
+ * **只红** `createWebSearchBackend` 的 switch:守卫链把 provider 收窄成旧三词,而旧三词是新 union 的
63
+ * 子集 ⇒ 赋值合法 ⇒ 改完 switch 全绿发版,`WEB_SEARCH_PROVIDER=<新词>` 却被判 undefined、能力位
64
+ * (`projectWebSearchCapability`)诚实报 `"none"`,运维以为自己配上了。收成一只元组之后:类型从它派生、
65
+ * 两只解析器读它、目录行**就用它本人**(身份相等有钉),规则集从四张表降到一张。
66
+ */
67
+ export declare const WEB_SEARCH_PROVIDERS: readonly ["brave", "tavily", "searxng"];
68
+ export type WebSearchProvider = (typeof WEB_SEARCH_PROVIDERS)[number];
69
+ /**
70
+ * S-382:`GET /v1/capabilities` 的 `webSearch` 位 —— **部署默认后端**的闭集自述。
71
+ *
72
+ * ## 病
73
+ * 「这台 worker 的搜索走哪只后端」此前只在 operator 面可知(`GET /v1/config/catalog` 的
74
+ * `WEB_SEARCH_PROVIDER` 行)。消费端(cli doctor / client-core 的能力投影)要答「本部署有没有搜索、
75
+ * 是哪一只」,只能让用户跑一个真任务去撞 —— 而搜索缺席时工具**根本不装配**(`capabilities/scenarios.ts`
76
+ * 的 `assembleCodeTools({ webSearch })`),模型只会说「我没有这个工具」,那句话在 UX 上与「后端配错了」
77
+ * 不可区分。
78
+ *
79
+ * ## 形
80
+ * `{ backend: "brave" | "tavily" | "searxng" | "none" }`。三条纪律逐条写明:
81
+ * ① **词源单点** —— 闭集是 {@link WebSearchProvider} **取型** ∪ `"none"`,而该类型又派生自
82
+ * {@link WEB_SEARCH_PROVIDERS}(全仓**唯一**一张 provider 词表:两只解析器读它、`config-catalog` 的
83
+ * `enumValues` **就用它本人**〔身份相等有钉〕)。加一只后端 = 改那只元组一处,这一位自动跟着长;
84
+ * 没跟上的地方只剩 `createWebSearchBackend` 的穷尽 `switch`,而那一处是**编译红**。
85
+ * ② **只出词,不出内情** —— 端点(SearXNG 实例 URL)、API key、配额一个字都不上这条 wire:本面在
86
+ * service-credential 门之后但**非 operator 专属**,任何拿得到凭据的调用方都读得到它。
87
+ * ③ **广告的是部署默认** —— 每请求的 `body.settings.webSearch`(单用户车道上**压过**部署座,见
88
+ * `capabilities/scenarios.ts` 的 default 场景)**刻意不在这一面回显**:那是请求方自己送进来的东西,
89
+ * 把它回显出去等于让能力面随调用方漂,而消费端正是拿这一位去渲「这台机器有没有搜索」的。
90
+ */
91
+ export interface WebSearchCapability {
92
+ readonly backend: WebSearchProvider | "none";
93
+ }
94
+ /**
95
+ * 部署席 → 消费端窄投影。**唯一**写 `"none"` 的地方(缺席折词的属主),形照 `projectSqlEngineCapability` /
96
+ * `projectWriteProtectionCapability`。
97
+ *
98
+ * 🔴 缺席折 `"none"` **不是**兜底 fail-open:`undefined`(装配没喂席位 / `WEB_SEARCH_PROVIDER` 未设或拼错)
99
+ * 与「本部署没有搜索后端」在**行为上是同一件事** —— `webSearchConfigFromEnv` 对这两种输入都返回
100
+ * `undefined`,于是 WebSearch 工具都不装配。方向也是安全的那一向:本位只会**少报**能力(说没有、其实
101
+ * 也真没有),不会替一台没配后端的部署点亮一格。「键整个缺席」才是另一回事(= 老 server),那一层由
102
+ * 消费端的探位纪律管,见契约附录 B.1 本行的「缺席何义」。
103
+ */
104
+ export declare function projectWebSearchCapability(provider: WebSearchProvider | undefined): WebSearchCapability;
57
105
  export interface WebSearchBackendConfig {
58
106
  readonly provider: WebSearchProvider;
59
107
  /** API key (brave/tavily). From `WEB_SEARCH_API_KEY` — never reaches the model. */
@@ -1,4 +1,11 @@
1
1
  import { createSearxngSearchBackend } from "@sema-agent/core";
2
+ export const WEB_SEARCH_PROVIDERS = ["brave", "tavily", "searxng"];
3
+ function isWebSearchProvider(word) {
4
+ return WEB_SEARCH_PROVIDERS.includes(word);
5
+ }
6
+ export function projectWebSearchCapability(provider) {
7
+ return provider === undefined ? { backend: "none" } : { backend: provider };
8
+ }
2
9
  const DEFAULT_MAX_RESULTS = 10;
3
10
  const DEFAULT_TIMEOUT_MS = 10_000;
4
11
  const BRAVE_BASE = "https://api.search.brave.com/res/v1/web/search";
@@ -152,7 +159,7 @@ export function shouldProbeWebSearchOnBoot(env = process.env) {
152
159
  }
153
160
  export function webSearchConfigFromEnv(env = process.env) {
154
161
  const provider = env.WEB_SEARCH_PROVIDER?.trim().toLowerCase();
155
- if (provider !== "brave" && provider !== "tavily" && provider !== "searxng")
162
+ if (provider === undefined || !isWebSearchProvider(provider))
156
163
  return undefined;
157
164
  const searxngParams = parseSearxngParams(env.WEB_SEARCH_SEARXNG_PARAMS);
158
165
  const maxRaw = Number(env.WEB_SEARCH_MAX_RESULTS ?? "");
@@ -171,7 +178,7 @@ export function webSearchConfigFromSettings(raw) {
171
178
  return undefined;
172
179
  const s = raw;
173
180
  const provider = typeof s.provider === "string" ? s.provider.trim().toLowerCase() : "";
174
- if (provider !== "brave" && provider !== "tavily" && provider !== "searxng")
181
+ if (!isWebSearchProvider(provider))
175
182
  return undefined;
176
183
  const max = typeof s.maxResults === "number" && Number.isFinite(s.maxResults) && s.maxResults > 0 ? Math.floor(s.maxResults) : undefined;
177
184
  return {
@@ -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.0",
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",
@@ -69,7 +69,7 @@
69
69
  "sharp": "^0.35.3"
70
70
  },
71
71
  "devDependencies": {
72
- "@sema-agent/sdk": "9.5.0",
72
+ "@sema-agent/sdk": "9.6.0",
73
73
  "@types/libsodium-wrappers": "^0.7.14",
74
74
  "@types/node": "22.10.2",
75
75
  "@types/pg": "^8.20.0",