@sema-agent/sdk 9.8.0 → 9.9.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.
@@ -1,7 +1,22 @@
1
- /** memory — 记忆面 = **memory-engine(DB twins)**:{@link MemoryResource.exportScope}
2
- * (`GET /v1/memory/export`)+ {@link MemoryResource.sync}(`POST /v1/memory/sync/:scope`)。
3
- * Owner-scoped BY CONSTRUCTION:scope 由请求 principal 推导(与任务执行同规则),调用方无法寻址他人的记忆;
4
- * 无 principal 头 → 401。
1
+ /** memory — 记忆面的两条车道,**受众不同,别混用**:
2
+ *
3
+ * ① **属主自助面**(memory-engine DB twins):{@link MemoryResource.exportScope}(`GET /v1/memory/export`)
4
+ * + {@link MemoryResource.sync}(`POST /v1/memory/sync/:scope`)。Owner-scoped BY CONSTRUCTION:scope 由
5
+ * 请求 principal 推导(与任务执行同规则),调用方无法寻址他人的记忆;无 principal 头 → 401。
6
+ * ② **operator / 合规面**(design/316 件③ + 件②,server ≥7.46.0;契约 §9 / §11):
7
+ * {@link MemoryResource.provenance} / {@link MemoryResource.erase} /
8
+ * {@link MemoryResource.originExternal} / {@link MemoryResource.originClearances} /
9
+ * {@link MemoryResource.originClear}。五口都是**部署级治理动作**(零模型工作、不计费),
10
+ * 门序逐字同一条:身份(401 `auth.principal_required`)→ 授权(403 `auth.operator_only`)→ 能力
11
+ * (501 `capability.memory_engine_required`)→ 验型(400)。**授权在能力之前**:一个够不着任何东西的
12
+ * 调用方不该从「这个部署有没有记忆引擎」上读出部署形态。
13
+ * 能力位**两位、刻意不是同义位**:件③ 两口读 `capabilities.memoryCompliance`,件② 三口读
14
+ * `capabilities.memoryOrigin`(今天同判据 —— 后端自带引擎控制面归属 `controlPlaneRoot` —— 但它们是
15
+ * 两个产品面,一个部署将来可能只开其中一族,合成一位会在分家那天对消费端说假话)。
16
+ * ⚠️ 两位都**不含**「凭据就绪」这一项:五口全在 server 的改写门里,没配 service 凭证且未显式开
17
+ * `ALLOW_UNAUTHED_WRITES` 的 worker 上,它们在**路由之前**被 503 `auth.service_token_required` 拦下,
18
+ * 而位仍为 `true`。消费端在那种部署上按 503 分支({@link import("../errors.js").ServiceStateError})。
19
+ * ⚠️ 位为真也**不**保证 `originExternal` 的答案完备 —— 见该动词的顶注。
5
20
  *
6
21
  * 🔴 BREAKING(SDK 1.0.0):legacy **MemoryStore** 面的五个动词(`get`/`clear`/`append`/`edit`/`remove`,
7
22
  * 对应 `GET|DELETE /v1/memory` 与 `POST|PATCH|DELETE /v1/sessions/:id/memory[/:noteId]`)已**整删**。
@@ -9,6 +24,7 @@
9
24
  * `memory:false` / `memoryWrite:false`,五个动词对现行 server 恒 404/501。留着 @deprecated 存根只会让
10
25
  * 下游代码编译得过、真机必炸 —— 删掉才让调用点当场红。迁移:改用上面两个 memory-engine 动词。 */
11
26
  import type { Transport } from "../transport.js";
27
+ import type { EntryProvenanceAccount, MemoryErasureAttestation, MemoryErasureRequest, MemoryOriginClearReceipt, MemoryOriginClearRequest, MemoryOriginClearancesResult, MemoryOriginExternalResult } from "../types.js";
12
28
  export declare class MemoryResource {
13
29
  private readonly t;
14
30
  constructor(t: Transport);
@@ -31,5 +47,136 @@ export declare class MemoryResource {
31
47
  sync(scope: string, body: Record<string, unknown>, opts?: {
32
48
  signal?: AbortSignal;
33
49
  }): Promise<Record<string, unknown>>;
50
+ /**
51
+ * GET /v1/memory/entries/:entryId/provenance — 一条 entry 的**出处账**(operator lane;契约 §9.2)。
52
+ *
53
+ * 200 体就是 core 的 {@link EntryProvenanceAccount} **本身**(server 不包一层、不投影、不补键:
54
+ * 账形是开放判别式,在中间层写一张白名单就是复述一份会随 core 漂移的结构)。
55
+ * 🔴 `binding` 与 `custody` 是**判别式**,按判别位分支;`{state:"unknown"}`(判不了)**绝不**折叠成
56
+ * `{state:"absent"}`(确实不存在)——两句话的合规结论相反。`custody.events` 的 `channel` 是**开集**,
57
+ * 别按固定形解析、也别写会抛的穷举 switch。
58
+ *
59
+ * ── 拒 ───────────────────────────────────────────────────────────────────────────────────────
60
+ * · 400 `request.id_invalid`(id 解码不出来)→ {@link import("../errors.js").BadRequestError};
61
+ * · 403 `auth.operator_only` → {@link import("../errors.js").AuthError};
62
+ * · 501 `capability.memory_engine_required` → {@link import("../errors.js").CapabilityUnavailableError}
63
+ * (换部署形态:要一个后端自带引擎控制面归属的记忆引擎;file 后端有,pg/tidb 没有);
64
+ * · 500 `internal.memory_control_plane_corrupt` → {@link import("../errors.js").InternalServerError} ——
65
+ * core 的 fail-closed 信号(控制面说不清,它宁可不答也不在说不清的账上拼一个答案)。
66
+ * 🔴 **一码两义、两义的运维动作相反**,而且 core 今天**没给判别位**:⑴ 操作前(lineage/challenges/
67
+ * 托管链账本读不出来)⇒ 什么都没发生,去修/重建账本;⑵ 落定后(**仅 erase**)⇒ 抹除与它的证据锚
68
+ * **已经提交**,只是残留枚举读失败。别去嗅 `message` 分辨(拿上游自由文本当判别式是第二真源,而这条
69
+ * 轴上判错的代价是「以为没删、其实删了」)—— core 的诊断文案原样透传,请完整展示给运维。
70
+ */
71
+ provenance(entryId: string, opts?: {
72
+ signal?: AbortSignal;
73
+ }): Promise<EntryProvenanceAccount>;
74
+ /**
75
+ * POST /v1/memory/erase — 显式授权的**合规抹除**(operator lane;契约 §9.3)。
76
+ *
77
+ * 请求体**逐字递交**(SDK 一个键都不加、不减、不改;尤其 `allowUnevidenced` **恒不注入** ——
78
+ * 降级腿是一次**人的**签字,中间层替他勾上就是替他签字)。200 体就是 core 的
79
+ * {@link MemoryErasureAttestation} 本身。
80
+ * 🔴 **先读 `evidenceCapability` 再决定能不能重试**:`"journal"` 腿上 `requestId` 是幂等身份(重试必须
81
+ * 复用同一个);`"none"` 腿上**重发就是第二次真删**(core 明写 replay convergence is not promised)——
82
+ * 不要给这一口配自动重试策略。
83
+ * ⚠️ **熔丝不适用**:整 scope / 整会话删除是**合法**选择子,core 的大规模删除熔丝对这条路显式不适用;
84
+ * `residuals.propagation: "local-store-only"` 是 core 的自陈边界(远端 peer 的收敛是同步部署自己那一半)。
85
+ *
86
+ * ── 拒 ───────────────────────────────────────────────────────────────────────────────────────
87
+ * · 400 `request.request_id_required`(缺席/空串/非串)→ BadRequestError。**与 `request.body_shape`
88
+ * 刻意分家**:本码说「铸一个稳定的 id 再发,而且重试必须复用同一个」,那个说「你的 JSON 形写错了」;
89
+ * · 400 `request.body_shape` → BadRequestError(顶层形不对,或选择子里混进了会重写对象原型的键);
90
+ * · 400 `config.memory_erasure_request` → BadRequestError —— **形对义错**(三选一没选对 / ids 空或重复…),
91
+ * 判决属主是 core;
92
+ * · 409 `memory.erasure_evidence_unavailable`(这个后端没有证据面而你没开降级腿)/
93
+ * `memory.erasure_selector_mismatch`(同一个 requestId 头一回用的是**另一个**选择子 ⇒ 换个新 id)/
94
+ * `memory.erasure_census_incomplete`(全店投影普查读不全,收执不能声称删干净了 ⇒ 修好文件系统再重试)
95
+ * → 三码都是 {@link import("../errors.js").ConflictError},**按 `errorCode` 分支**(status 分不出来);
96
+ * · 403 / 501 / 500 同 {@link provenance}。
97
+ */
98
+ erase(body: MemoryErasureRequest, opts?: {
99
+ signal?: AbortSignal;
100
+ }): Promise<MemoryErasureAttestation>;
101
+ /**
102
+ * GET /v1/memory/origin/external?scopes=a,b — 点名 scope 里每一条**带外源标记**的条目 + 它的完整出处账
103
+ * (operator lane;契约 §11.2)。
104
+ *
105
+ * 🔴 **答案只覆盖你点名的那些 scope,空结果绝不读作「本店干净」。** server 这一代没有 scope 枚举读面,
106
+ * 所以 scope 名必须由调用方给;不完备是**静默**的(空数组与「这些 scope 干净」在 wire 上同形)。
107
+ * 回执里的 `scopes` 是**这次真正被审的那一份**(服务端逐段去空白、去空段、保序去重之后)——
108
+ * 消费端不该靠自己记得发了什么去反推答案的边界。
109
+ *
110
+ * ── 编码 ─────────────────────────────────────────────────────────────────────────────────────
111
+ * 每个 scope 键**逐段 `encodeURIComponent`** 之后才用 `,` 连(scope 键含 `:` / `@` / `/`;服务端读法是
112
+ * `URLSearchParams.getAll("scopes")` → 逐段 `split(",")`,所以分隔符必须活在已编码的值之外)。
113
+ * ⚠️ 如实登记一条 wire 上的表达力边界:**scope 键里的字面逗号在这条查询串上不可表达**(它会被服务端
114
+ * 先解码、再当分隔符切开)。本仓的 scope 词表今天不含逗号;真出现那天要改的是 server 的编码约定,不是
115
+ * 在这里偷偷换一种编码(那就成了两个写者)。
116
+ * `originAware=1` 由 SDK **无条件**声明,理由见 {@link ORIGIN_AWARE_QS}。
117
+ *
118
+ * ── 拒 ───────────────────────────────────────────────────────────────────────────────────────
119
+ * · 400 `request.query_invalid`(名单为空 / 归一化后为空)→ BadRequestError —— 文案里直接写着「空答
120
+ * 绝不读作本店干净」与 scope 名从哪儿拿;
121
+ * · 403 / 501 / 500 同 {@link provenance}。
122
+ */
123
+ originExternal(scopes: string[], opts?: {
124
+ signal?: AbortSignal;
125
+ }): Promise<MemoryOriginExternalResult>;
126
+ /**
127
+ * GET /v1/memory/origin/clearances — **清标审计账**(operator lane;契约 §11.3)。
128
+ *
129
+ * 每一行是 core `OriginClearanceRow` 的**显式白名单投影**:被剥的 core 键只有一个 —— `entryText`
130
+ * (被清标条目的**完整正文**),而且**剥了要说**(`custodyBytes` 是它留在审计面上的那句披露)。
131
+ * 🔴 `custodyBytes > 0` 的 `pending` 行 = 崩溃恢复席里还揣着一条记忆的正文,**要人处置**;恢复的手段
132
+ * 是**再调一次 {@link originClear}**(引擎自己从行里重放),不是把字节读出来贴回去。
133
+ * 🔴 归属是**自称**的:`requestId` 由调用方自己填、引擎原样落账。部署侧的对照物在 server 日志
134
+ * (`memory_origin_cleared`,带**已验证的** principal + 调用方自称的 requestId + `clearanceId`)——
135
+ * **合规结论不要只读账本**。
136
+ *
137
+ * 拒:403 / 501 / 500 同 {@link provenance}。本口无查询参数、无请求体。
138
+ */
139
+ originClearances(opts?: {
140
+ signal?: AbortSignal;
141
+ }): Promise<MemoryOriginClearancesResult>;
142
+ /**
143
+ * POST /v1/memory/origin/entries/:entryId/clear — 审计化的 **UN-MARK 阀门**(operator lane;契约 §11.4)。
144
+ *
145
+ * 它把「这条记忆来自外部、用前先核」这句披露**替宿主担保掉** —— 签字的人必须是部署的操作员。清标走的
146
+ * 是后端不可变律的**唯一合法出口**:写前清标行(托管 = 完整正文)→ 已提交的墓碑(CAS 在判决的 rev 上)
147
+ * → 后一批以**同一个 id** 重录一条剥掉标记的条目(同 id 是故意的:链接、使用账、清标 join 都保住自己的
148
+ * 键)。每一次失败都让托管行**留在原地**,而**再调一次同一口就是恢复**(幂等)。
149
+ *
150
+ * 🔴 **`requestId` 是审计归属,不是幂等键**(与 {@link erase} 的同名字段语义相反,别互相套用):恢复
151
+ * 一条 pending 行时传一个**新的** id 是合法且常见的。
152
+ * 🔴 **200 不带「这是一次恢复」的判别位**,而恢复腿**一个字都不看你的 `reason`** ⇒ 拿到 200 之后回读
153
+ * {@link originClearances} 对一次 `reason` / `requestId`,别把 200 读成「我的理由已入账」。
154
+ *
155
+ * ── 拒(**逐码**;409 六码全是 {@link import("../errors.js").ConflictError},按 `errorCode` 分支)─────
156
+ * · 400 `request.id_invalid` / `request.request_id_required` / `request.body_shape` → BadRequestError;
157
+ * · **422**(语义拒:体是合法 JSON、形也对,拒的是**义**)—— 码原样透传,SDK 侧落**带码的**
158
+ * {@link import("../errors.js").APIError}(本 SDK 今天没有 422 这一档的专属类;按 `errorCode` 分支):
159
+ * · `memory.origin_clear_unattributed` —— 空 `requestId`(core 原话:refused, never defaulted)。
160
+ * ⚠️ 经本仓的路由它今天**到不了** core(路由自己的 zod 门先答 400 `request.request_id_required`);
161
+ * · `memory.origin_clear_invalid` —— 空 `reason`(这一条**真能上 wire**:server 刻意不抄 min(1));
162
+ * · **409**(状态与请求的分歧 / 并发 / 半路可续,六条运维动作各不相同,禁折成一格):
163
+ * · `memory.origin_clear_unknown` —— **一码两义**:⑴ 这个 id 上没有已提交的条目(核对 id);⑵ 一条
164
+ * **被恢复**的清标行,其条目已不在店里而这次清标从未记过墓碑 ⇒ core 判「这次删除不是本清标做的,
165
+ * 不予复活」,托管字节留在终态行上待人查。刻意**不落 404**(⑵ 根本不是「资源不存在」);
166
+ * · `memory.origin_clear_not_marked` —— 条目在,但它本来就没有外源标记(先用 {@link originExternal} 看清谁真被标了);
167
+ * · `memory.origin_clear_challenged` —— 条目被挑战/latch 住。**清标阀门不是挑战的出口**:先把挑战裁掉
168
+ * (拿一张更弱的凭据去洗掉一次排除,正是这一条要拦的形);
169
+ * · `memory.origin_clear_conflict` —— 判据自清标开行以来动了(rev 变 / 投影 slug 变 / 盘上有未收编的
170
+ * 改动 / 墓碑腿被拒)⇒ 再调一次重判(**两侧字节零变更**);
171
+ * · `memory.origin_clear_failed` —— 停在**半路且可续**(重录腿被拒 / 托管字节自检不过),行保持
172
+ * `pending`、托管字节还在 ⇒ 修好后再调一次**恢复**它。⚠️ 别读成「什么都没发生」:墓碑可能**已经
173
+ * 提交**了,`originClearances()` 上那一行的 `custodyBytes` 就是告示;
174
+ * · `memory.origin_clear_pending` —— 同一条 entry 上**已经有一行 pending**(core 原话:the pending row
175
+ * is a resume seat, not a queue)。这是**并发**不是故障 ⇒ 重发,下一次会走进恢复腿;
176
+ * · 403 / 501 / 500 同 {@link provenance}。
177
+ */
178
+ originClear(entryId: string, body: MemoryOriginClearRequest, opts?: {
179
+ signal?: AbortSignal;
180
+ }): Promise<MemoryOriginClearReceipt>;
34
181
  }
35
182
  //# sourceMappingURL=memory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/resources/memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;8DAS8D;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC;;oDAEgD;IAC1C,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,EAAE,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAI3J;;;;0DAIsD;IAChD,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAG5H"}
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/resources/memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;8DAwB8D;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EACV,sBAAsB,EACtB,wBAAwB,EACxB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,4BAA4B,EAC5B,0BAA0B,EAC3B,MAAM,aAAa,CAAC;AAoBrB,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC;;oDAEgD;IAC1C,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,EAAE,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAI3J;;;;0DAIsD;IAChD,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAQ3H;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAQnG;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACG,KAAK,CAAC,IAAI,EAAE,oBAAoB,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAa3G;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAS5G;;;;;;;;;;;;OAYG;IACG,gBAAgB,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAQ9F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,wBAAwB,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,wBAAwB,CAAC;CAQvI"}
@@ -1,3 +1,20 @@
1
+ /**
2
+ * design/383 S-6 / S-50 §三(F3)的 **origin 围栏**能力位。
3
+ *
4
+ * 缺省(不带这一位)下,server 对每一个投影带 origin 标条目的读口**整条扣留**带标条目,并在响应上补一个
5
+ * `withheldOriginTagged: <n>` 计数 —— 因为它没有 per-client 版本可见性,只能假定「不声明 = 老客户端」,
6
+ * 而老客户端的 strict/strip parse 会**静默剥掉** origin 标,把一条「外源已标」的条目摊平成无标文本,
7
+ * 消费端再把它当洁净内容引用/回写 = 出处被洗掉。
8
+ *
9
+ * 🔴 本 SDK 在 `originExternal` 上**无条件**声明它,而且**不给旋钮**:该动词的回执型
10
+ * ({@link import("../types.js").MemoryOriginExternalEntry})具名了 `origin` 键族,所以本 SDK 按构造就是
11
+ * origin-aware —— 一个能关掉它的参数等于让调用方申报一句假话,而那一口的每一条都带标,关掉它只会拿到
12
+ * 一份自称干净、其实被围栏扣光了的空名单(这一口最危险的失败形正是「静默的不完备」)。
13
+ * ⚠️ 反过来,{@link MemoryResource.exportScope} **刻意不带**这一位:它的 `entries` 今天是 `unknown[]`,
14
+ * 型面上一个 origin 键都没具名 ⇒ 它**不是** origin-aware,替它声明就是同一句假话。那条读口的收编是
15
+ * 独立的一车(要先给 entry 具名型面),不在本族射程内。
16
+ */
17
+ const ORIGIN_AWARE_QS = "originAware=1";
1
18
  export class MemoryResource {
2
19
  t;
3
20
  constructor(t) {
@@ -17,5 +34,165 @@ export class MemoryResource {
17
34
  async sync(scope, body, opts) {
18
35
  return this.t.request({ method: "POST", path: `/v1/memory/sync/${encodeURIComponent(scope)}`, body, signal: opts?.signal });
19
36
  }
37
+ // ═════════════════════════════════════════════════════════════════════════════════════════════
38
+ // design/316 件③ —— 出处 / 抹除合规面(契约 §9)
39
+ // ═════════════════════════════════════════════════════════════════════════════════════════════
40
+ /**
41
+ * GET /v1/memory/entries/:entryId/provenance — 一条 entry 的**出处账**(operator lane;契约 §9.2)。
42
+ *
43
+ * 200 体就是 core 的 {@link EntryProvenanceAccount} **本身**(server 不包一层、不投影、不补键:
44
+ * 账形是开放判别式,在中间层写一张白名单就是复述一份会随 core 漂移的结构)。
45
+ * 🔴 `binding` 与 `custody` 是**判别式**,按判别位分支;`{state:"unknown"}`(判不了)**绝不**折叠成
46
+ * `{state:"absent"}`(确实不存在)——两句话的合规结论相反。`custody.events` 的 `channel` 是**开集**,
47
+ * 别按固定形解析、也别写会抛的穷举 switch。
48
+ *
49
+ * ── 拒 ───────────────────────────────────────────────────────────────────────────────────────
50
+ * · 400 `request.id_invalid`(id 解码不出来)→ {@link import("../errors.js").BadRequestError};
51
+ * · 403 `auth.operator_only` → {@link import("../errors.js").AuthError};
52
+ * · 501 `capability.memory_engine_required` → {@link import("../errors.js").CapabilityUnavailableError}
53
+ * (换部署形态:要一个后端自带引擎控制面归属的记忆引擎;file 后端有,pg/tidb 没有);
54
+ * · 500 `internal.memory_control_plane_corrupt` → {@link import("../errors.js").InternalServerError} ——
55
+ * core 的 fail-closed 信号(控制面说不清,它宁可不答也不在说不清的账上拼一个答案)。
56
+ * 🔴 **一码两义、两义的运维动作相反**,而且 core 今天**没给判别位**:⑴ 操作前(lineage/challenges/
57
+ * 托管链账本读不出来)⇒ 什么都没发生,去修/重建账本;⑵ 落定后(**仅 erase**)⇒ 抹除与它的证据锚
58
+ * **已经提交**,只是残留枚举读失败。别去嗅 `message` 分辨(拿上游自由文本当判别式是第二真源,而这条
59
+ * 轴上判错的代价是「以为没删、其实删了」)—— core 的诊断文案原样透传,请完整展示给运维。
60
+ */
61
+ async provenance(entryId, opts) {
62
+ return this.t.request({
63
+ method: "GET",
64
+ path: `/v1/memory/entries/${encodeURIComponent(entryId)}/provenance`,
65
+ signal: opts?.signal,
66
+ });
67
+ }
68
+ /**
69
+ * POST /v1/memory/erase — 显式授权的**合规抹除**(operator lane;契约 §9.3)。
70
+ *
71
+ * 请求体**逐字递交**(SDK 一个键都不加、不减、不改;尤其 `allowUnevidenced` **恒不注入** ——
72
+ * 降级腿是一次**人的**签字,中间层替他勾上就是替他签字)。200 体就是 core 的
73
+ * {@link MemoryErasureAttestation} 本身。
74
+ * 🔴 **先读 `evidenceCapability` 再决定能不能重试**:`"journal"` 腿上 `requestId` 是幂等身份(重试必须
75
+ * 复用同一个);`"none"` 腿上**重发就是第二次真删**(core 明写 replay convergence is not promised)——
76
+ * 不要给这一口配自动重试策略。
77
+ * ⚠️ **熔丝不适用**:整 scope / 整会话删除是**合法**选择子,core 的大规模删除熔丝对这条路显式不适用;
78
+ * `residuals.propagation: "local-store-only"` 是 core 的自陈边界(远端 peer 的收敛是同步部署自己那一半)。
79
+ *
80
+ * ── 拒 ───────────────────────────────────────────────────────────────────────────────────────
81
+ * · 400 `request.request_id_required`(缺席/空串/非串)→ BadRequestError。**与 `request.body_shape`
82
+ * 刻意分家**:本码说「铸一个稳定的 id 再发,而且重试必须复用同一个」,那个说「你的 JSON 形写错了」;
83
+ * · 400 `request.body_shape` → BadRequestError(顶层形不对,或选择子里混进了会重写对象原型的键);
84
+ * · 400 `config.memory_erasure_request` → BadRequestError —— **形对义错**(三选一没选对 / ids 空或重复…),
85
+ * 判决属主是 core;
86
+ * · 409 `memory.erasure_evidence_unavailable`(这个后端没有证据面而你没开降级腿)/
87
+ * `memory.erasure_selector_mismatch`(同一个 requestId 头一回用的是**另一个**选择子 ⇒ 换个新 id)/
88
+ * `memory.erasure_census_incomplete`(全店投影普查读不全,收执不能声称删干净了 ⇒ 修好文件系统再重试)
89
+ * → 三码都是 {@link import("../errors.js").ConflictError},**按 `errorCode` 分支**(status 分不出来);
90
+ * · 403 / 501 / 500 同 {@link provenance}。
91
+ */
92
+ async erase(body, opts) {
93
+ return this.t.request({
94
+ method: "POST",
95
+ path: "/v1/memory/erase",
96
+ body,
97
+ signal: opts?.signal,
98
+ });
99
+ }
100
+ // ═════════════════════════════════════════════════════════════════════════════════════════════
101
+ // design/316 件② —— 外源标记人面(契约 §11)
102
+ // ═════════════════════════════════════════════════════════════════════════════════════════════
103
+ /**
104
+ * GET /v1/memory/origin/external?scopes=a,b — 点名 scope 里每一条**带外源标记**的条目 + 它的完整出处账
105
+ * (operator lane;契约 §11.2)。
106
+ *
107
+ * 🔴 **答案只覆盖你点名的那些 scope,空结果绝不读作「本店干净」。** server 这一代没有 scope 枚举读面,
108
+ * 所以 scope 名必须由调用方给;不完备是**静默**的(空数组与「这些 scope 干净」在 wire 上同形)。
109
+ * 回执里的 `scopes` 是**这次真正被审的那一份**(服务端逐段去空白、去空段、保序去重之后)——
110
+ * 消费端不该靠自己记得发了什么去反推答案的边界。
111
+ *
112
+ * ── 编码 ─────────────────────────────────────────────────────────────────────────────────────
113
+ * 每个 scope 键**逐段 `encodeURIComponent`** 之后才用 `,` 连(scope 键含 `:` / `@` / `/`;服务端读法是
114
+ * `URLSearchParams.getAll("scopes")` → 逐段 `split(",")`,所以分隔符必须活在已编码的值之外)。
115
+ * ⚠️ 如实登记一条 wire 上的表达力边界:**scope 键里的字面逗号在这条查询串上不可表达**(它会被服务端
116
+ * 先解码、再当分隔符切开)。本仓的 scope 词表今天不含逗号;真出现那天要改的是 server 的编码约定,不是
117
+ * 在这里偷偷换一种编码(那就成了两个写者)。
118
+ * `originAware=1` 由 SDK **无条件**声明,理由见 {@link ORIGIN_AWARE_QS}。
119
+ *
120
+ * ── 拒 ───────────────────────────────────────────────────────────────────────────────────────
121
+ * · 400 `request.query_invalid`(名单为空 / 归一化后为空)→ BadRequestError —— 文案里直接写着「空答
122
+ * 绝不读作本店干净」与 scope 名从哪儿拿;
123
+ * · 403 / 501 / 500 同 {@link provenance}。
124
+ */
125
+ async originExternal(scopes, opts) {
126
+ const qs = scopes.map(encodeURIComponent).join(",");
127
+ return this.t.request({
128
+ method: "GET",
129
+ path: `/v1/memory/origin/external?scopes=${qs}&${ORIGIN_AWARE_QS}`,
130
+ signal: opts?.signal,
131
+ });
132
+ }
133
+ /**
134
+ * GET /v1/memory/origin/clearances — **清标审计账**(operator lane;契约 §11.3)。
135
+ *
136
+ * 每一行是 core `OriginClearanceRow` 的**显式白名单投影**:被剥的 core 键只有一个 —— `entryText`
137
+ * (被清标条目的**完整正文**),而且**剥了要说**(`custodyBytes` 是它留在审计面上的那句披露)。
138
+ * 🔴 `custodyBytes > 0` 的 `pending` 行 = 崩溃恢复席里还揣着一条记忆的正文,**要人处置**;恢复的手段
139
+ * 是**再调一次 {@link originClear}**(引擎自己从行里重放),不是把字节读出来贴回去。
140
+ * 🔴 归属是**自称**的:`requestId` 由调用方自己填、引擎原样落账。部署侧的对照物在 server 日志
141
+ * (`memory_origin_cleared`,带**已验证的** principal + 调用方自称的 requestId + `clearanceId`)——
142
+ * **合规结论不要只读账本**。
143
+ *
144
+ * 拒:403 / 501 / 500 同 {@link provenance}。本口无查询参数、无请求体。
145
+ */
146
+ async originClearances(opts) {
147
+ return this.t.request({
148
+ method: "GET",
149
+ path: "/v1/memory/origin/clearances",
150
+ signal: opts?.signal,
151
+ });
152
+ }
153
+ /**
154
+ * POST /v1/memory/origin/entries/:entryId/clear — 审计化的 **UN-MARK 阀门**(operator lane;契约 §11.4)。
155
+ *
156
+ * 它把「这条记忆来自外部、用前先核」这句披露**替宿主担保掉** —— 签字的人必须是部署的操作员。清标走的
157
+ * 是后端不可变律的**唯一合法出口**:写前清标行(托管 = 完整正文)→ 已提交的墓碑(CAS 在判决的 rev 上)
158
+ * → 后一批以**同一个 id** 重录一条剥掉标记的条目(同 id 是故意的:链接、使用账、清标 join 都保住自己的
159
+ * 键)。每一次失败都让托管行**留在原地**,而**再调一次同一口就是恢复**(幂等)。
160
+ *
161
+ * 🔴 **`requestId` 是审计归属,不是幂等键**(与 {@link erase} 的同名字段语义相反,别互相套用):恢复
162
+ * 一条 pending 行时传一个**新的** id 是合法且常见的。
163
+ * 🔴 **200 不带「这是一次恢复」的判别位**,而恢复腿**一个字都不看你的 `reason`** ⇒ 拿到 200 之后回读
164
+ * {@link originClearances} 对一次 `reason` / `requestId`,别把 200 读成「我的理由已入账」。
165
+ *
166
+ * ── 拒(**逐码**;409 六码全是 {@link import("../errors.js").ConflictError},按 `errorCode` 分支)─────
167
+ * · 400 `request.id_invalid` / `request.request_id_required` / `request.body_shape` → BadRequestError;
168
+ * · **422**(语义拒:体是合法 JSON、形也对,拒的是**义**)—— 码原样透传,SDK 侧落**带码的**
169
+ * {@link import("../errors.js").APIError}(本 SDK 今天没有 422 这一档的专属类;按 `errorCode` 分支):
170
+ * · `memory.origin_clear_unattributed` —— 空 `requestId`(core 原话:refused, never defaulted)。
171
+ * ⚠️ 经本仓的路由它今天**到不了** core(路由自己的 zod 门先答 400 `request.request_id_required`);
172
+ * · `memory.origin_clear_invalid` —— 空 `reason`(这一条**真能上 wire**:server 刻意不抄 min(1));
173
+ * · **409**(状态与请求的分歧 / 并发 / 半路可续,六条运维动作各不相同,禁折成一格):
174
+ * · `memory.origin_clear_unknown` —— **一码两义**:⑴ 这个 id 上没有已提交的条目(核对 id);⑵ 一条
175
+ * **被恢复**的清标行,其条目已不在店里而这次清标从未记过墓碑 ⇒ core 判「这次删除不是本清标做的,
176
+ * 不予复活」,托管字节留在终态行上待人查。刻意**不落 404**(⑵ 根本不是「资源不存在」);
177
+ * · `memory.origin_clear_not_marked` —— 条目在,但它本来就没有外源标记(先用 {@link originExternal} 看清谁真被标了);
178
+ * · `memory.origin_clear_challenged` —— 条目被挑战/latch 住。**清标阀门不是挑战的出口**:先把挑战裁掉
179
+ * (拿一张更弱的凭据去洗掉一次排除,正是这一条要拦的形);
180
+ * · `memory.origin_clear_conflict` —— 判据自清标开行以来动了(rev 变 / 投影 slug 变 / 盘上有未收编的
181
+ * 改动 / 墓碑腿被拒)⇒ 再调一次重判(**两侧字节零变更**);
182
+ * · `memory.origin_clear_failed` —— 停在**半路且可续**(重录腿被拒 / 托管字节自检不过),行保持
183
+ * `pending`、托管字节还在 ⇒ 修好后再调一次**恢复**它。⚠️ 别读成「什么都没发生」:墓碑可能**已经
184
+ * 提交**了,`originClearances()` 上那一行的 `custodyBytes` 就是告示;
185
+ * · `memory.origin_clear_pending` —— 同一条 entry 上**已经有一行 pending**(core 原话:the pending row
186
+ * is a resume seat, not a queue)。这是**并发**不是故障 ⇒ 重发,下一次会走进恢复腿;
187
+ * · 403 / 501 / 500 同 {@link provenance}。
188
+ */
189
+ async originClear(entryId, body, opts) {
190
+ return this.t.request({
191
+ method: "POST",
192
+ path: `/v1/memory/origin/entries/${encodeURIComponent(entryId)}/clear`,
193
+ body,
194
+ signal: opts?.signal,
195
+ });
196
+ }
20
197
  }
21
198
  //# sourceMappingURL=memory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/resources/memory.ts"],"names":[],"mappings":"AAYA,MAAM,OAAO,cAAc;IACI;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C;;oDAEgD;IAChD,KAAK,CAAC,WAAW,CAAC,KAAa,EAAE,IAA+B;QAC9D,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,2BAA2B,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/H,CAAC;IAED;;;;0DAIsD;IACtD,KAAK,CAAC,IAAI,CAAC,KAAa,EAAE,IAA6B,EAAE,IAA+B;QACtF,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC9H,CAAC;CACF"}
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/resources/memory.ts"],"names":[],"mappings":"AAoCA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,eAAe,GAAG,eAAe,CAAC;AAExC,MAAM,OAAO,cAAc;IACI;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C;;oDAEgD;IAChD,KAAK,CAAC,WAAW,CAAC,KAAa,EAAE,IAA+B;QAC9D,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,2BAA2B,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/H,CAAC;IAED;;;;0DAIsD;IACtD,KAAK,CAAC,IAAI,CAAC,KAAa,EAAE,IAA6B,EAAE,IAA+B;QACtF,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC9H,CAAC;IAED,gGAAgG;IAChG,qCAAqC;IACrC,gGAAgG;IAEhG;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,KAAK,CAAC,UAAU,CAAC,OAAe,EAAE,IAA+B;QAC/D,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAyB;YAC5C,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,sBAAsB,kBAAkB,CAAC,OAAO,CAAC,aAAa;YACpE,MAAM,EAAE,IAAI,EAAE,MAAM;SACrB,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,KAAK,CAAC,KAAK,CAAC,IAA0B,EAAE,IAA+B;QACrE,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAA2B;YAC9C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,kBAAkB;YACxB,IAAI;YACJ,MAAM,EAAE,IAAI,EAAE,MAAM;SACrB,CAAC,CAAC;IACL,CAAC;IAED,gGAAgG;IAChG,kCAAkC;IAClC,gGAAgG;IAEhG;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,KAAK,CAAC,cAAc,CAAC,MAAgB,EAAE,IAA+B;QACpE,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAA6B;YAChD,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,qCAAqC,EAAE,IAAI,eAAe,EAAE;YAClE,MAAM,EAAE,IAAI,EAAE,MAAM;SACrB,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,gBAAgB,CAAC,IAA+B;QACpD,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAA+B;YAClD,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,8BAA8B;YACpC,MAAM,EAAE,IAAI,EAAE,MAAM;SACrB,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACH,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,IAA8B,EAAE,IAA+B;QAChG,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAA2B;YAC9C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,6BAA6B,kBAAkB,CAAC,OAAO,CAAC,QAAQ;YACtE,IAAI;YACJ,MAAM,EAAE,IAAI,EAAE,MAAM;SACrB,CAAC,CAAC;IACL,CAAC;CACF"}