@sema-agent/sdk 6.12.0 → 6.13.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.
- package/dist/client.d.ts +9 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +11 -0
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +15 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +27 -2
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/resources/adoption.d.ts +196 -0
- package/dist/resources/adoption.d.ts.map +1 -0
- package/dist/resources/adoption.js +55 -0
- package/dist/resources/adoption.js.map +1 -0
- package/dist/resources/rules.d.ts +175 -0
- package/dist/resources/rules.d.ts.map +1 -0
- package/dist/resources/rules.js +40 -0
- package/dist/resources/rules.js.map +1 -0
- package/dist/resources/tool-approvals.d.ts +111 -2
- package/dist/resources/tool-approvals.d.ts.map +1 -1
- package/dist/resources/tool-approvals.js +12 -0
- package/dist/resources/tool-approvals.js.map +1 -1
- package/dist/resources/trace.d.ts +30 -1
- package/dist/resources/trace.d.ts.map +1 -1
- package/dist/resources/trace.js +38 -0
- package/dist/resources/trace.js.map +1 -1
- package/dist/types.d.ts +25 -0
- package/dist/types.d.ts.map +1 -1
- package/openapi.yaml +868 -3
- package/package.json +1 -1
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* adoption — **身份收编**(design/183 form b:纯身份重绑;server `src/http/routes/adoption.ts` +
|
|
3
|
+
* `src/adoption/wire.ts`)。
|
|
4
|
+
*
|
|
5
|
+
* `start({fromPrincipal, toPrincipal})` → POST /v1/adoption — 发起(幂等)
|
|
6
|
+
* `get(adoptionId)` → GET /v1/adoption/{id} — 读状态
|
|
7
|
+
*
|
|
8
|
+
* 形态:一次性的**部署级动作**,不是常驻业务面 —— operator-only、零模型工作(不计费)、没有 SQL 后端的
|
|
9
|
+
* 部署上诚实 501(收编重绑的是多租身份轴,local 后端根本没有那个轴)。
|
|
10
|
+
*
|
|
11
|
+
* ── 三条硬语义(照抄自 server 的 wire schema,消费端按它写围栏)────────────────────────────────────
|
|
12
|
+
* ① **一种包络**:首次成功与一切幂等重跑同形({@link AdoptionReceipt});别处不得另造第二种回执。
|
|
13
|
+
* ⚠️ 「同形」≠「保证同字节」:**终态之后**重跑回放的是**同一份** `immutableReport`(phase 6 一次落库,
|
|
14
|
+
* 此后逐字节原样回放);但 `current` **每次现算**,所以整份回执**没有**逐字节相同的保证 —— 账没动时
|
|
15
|
+
* 它可能恰好相同,动了就不同,两种都合约内。终态之前(`stalled`)连报告本身都是当前行的临时投影
|
|
16
|
+
* —— 判据是 `status`,不是字段名里的 immutable。
|
|
17
|
+
* ② **被拒的收编从不产出回执**:`status` 闭集只有 `adopted`/`stalled`,**没有 `rejected`** —— 拒一律是
|
|
18
|
+
* typed 409(`adoption.source_already_bound` / `adoption.destination_conflict` /
|
|
19
|
+
* `adoption.destination_unrepresentable`,SDK 侧落 {@link import("../errors.js").ConflictError},按
|
|
20
|
+
* `errorCode` 分支)。否则「拒」与「成」共用一个 200 包络,消费端只能读字段猜。
|
|
21
|
+
* ③ **史实与现势分家**:`immutableReport` 是终态快照(**终态之后**恒同),`current` 每次现算。别从其中一半推另一半 ——
|
|
22
|
+
* 尤其别把 `status: "adopted"` 读成「配置也随迁完了」:那笔账在 `current.outstandingConfigs` /
|
|
23
|
+
* `current.residualSourceRows` 上。
|
|
24
|
+
*
|
|
25
|
+
* ⚠️ **收编不给普通写者上栅栏**:「引擎必须先停」是**运维前提**,不是机器保证。一个还在按旧身份注入的
|
|
26
|
+
* 调用方会在终态之后继续往旧身份下写行,而终态 + 幂等短路会让回执一直说 `adopted` ——
|
|
27
|
+
* {@link AdoptionCurrent.residualSourceRows} 就是把那件事变成可见读数的地方。
|
|
28
|
+
*/
|
|
29
|
+
import type { Transport } from "../transport.js";
|
|
30
|
+
/** `POST /v1/adoption` 的请求体(server 侧 `.strict()`:多一个键 = 400)。 */
|
|
31
|
+
export interface AdoptionRequest {
|
|
32
|
+
/** 被收编的旧身份。已绑到**别的**目的地 ⇒ 409 `adoption.source_already_bound`(D7,非本协议射程)。 */
|
|
33
|
+
fromPrincipal: string;
|
|
34
|
+
/** 收编到的既存身份。与 `fromPrincipal` 同名 ⇒ 400(那是提错了的请求,不是一次无操作的成功)。 */
|
|
35
|
+
toPrincipal: string;
|
|
36
|
+
}
|
|
37
|
+
/** 收编来源。form b 只有具名 principal 一形(`local-owner` 是 form a 的形,本版不产出也不接受)。 */
|
|
38
|
+
export interface AdoptionSource {
|
|
39
|
+
kind: "principal";
|
|
40
|
+
principal: string;
|
|
41
|
+
}
|
|
42
|
+
/** per-store 迁移腿的动作词(闭集;form b 只会产出前两个 + `none`)。 */
|
|
43
|
+
export type AdoptionLegAction = "bucket-rebind" | "row-rewrite" | "carried" | "none" | "reset";
|
|
44
|
+
/** 一条迁移腿的回执。 */
|
|
45
|
+
export interface AdoptionLeg {
|
|
46
|
+
/** 腿的稳定标识 = `<表名>#<身份轴列>`(server schema 的真名;下游按它对账)。 */
|
|
47
|
+
store: string;
|
|
48
|
+
action: AdoptionLegAction;
|
|
49
|
+
/**
|
|
50
|
+
* 这条腿**跑的时候**改了几行。
|
|
51
|
+
*
|
|
52
|
+
* 🔴 **不是「本次请求改了几行」**(codex 交叉复审 [medium],亲读 `receiptOf` 验真):腿只在
|
|
53
|
+
* `immutableReport` 里露面,而终态之后那份报告是从 `report_json` 原样读回的 ⇒ **每次重跑都回放首次的
|
|
54
|
+
* 读数**。所以看到一个非 0 值,说明的是「当初那次迁了这么多」,**不是**「刚才这次干了活」;迟到行的
|
|
55
|
+
* 清扫(POST 的 sweep)也不会改写它。要看现在还剩多少,读 {@link AdoptionCurrent.residualSourceRows}。
|
|
56
|
+
* `stalled` 的回执上它是当前行的读数,还会动。
|
|
57
|
+
*/
|
|
58
|
+
rows?: number;
|
|
59
|
+
quarantined?: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* 一条受影响的**部署配置**。
|
|
63
|
+
*
|
|
64
|
+
* 🔴 `migrated` 对 server 半场**恒 false**:这些配置全在别的部署单元(BFF / cli / env / core 声明位),
|
|
65
|
+
* 收编动作够不到它们 —— 改不到的配置,不假装改了。清单在场 + `migrated:false` + 账不清,三件一起才是
|
|
66
|
+
* 「配置不迁如实红」的凭据。
|
|
67
|
+
*/
|
|
68
|
+
export interface AdoptionConfigEntry {
|
|
69
|
+
deployment: string;
|
|
70
|
+
key: string;
|
|
71
|
+
requiredValue: string;
|
|
72
|
+
/** 恒 `false`(见上)。 */
|
|
73
|
+
migrated: boolean;
|
|
74
|
+
/** 运维表态位 —— **只作记录,不清账**(手写布尔可以把账清成假绿)。 */
|
|
75
|
+
ack: boolean;
|
|
76
|
+
/** 消费端运行时真读回 `requiredValue` 的 typed 回执时刻。🔴 **`null` = 未见证 = 未清账**。 */
|
|
77
|
+
witnessedAtMs: number | null;
|
|
78
|
+
}
|
|
79
|
+
/** **冻结的机读词表**:server 侧按设计不迁的面。加成员 = 加行为面,减成员 = 下游围栏红。 */
|
|
80
|
+
export type AdoptionNotMigratedFace = "usage-window" | "cost-quota" | "rate-limit" | "approval-exemption-grantor" | "approval-ask-decision-actor" | "image-bake-requested-by";
|
|
81
|
+
/** 一条「按设计不迁」的**正向声明** —— 它存在的全部意义是让「按设计不迁」与「漏了没迁」在黑盒上可分。 */
|
|
82
|
+
export interface AdoptionNotMigrated {
|
|
83
|
+
face: AdoptionNotMigratedFace;
|
|
84
|
+
/** design/183 §12 的裁决号:`D1` = 配额窗清零重计;`D2` = 史实字段不改写。 */
|
|
85
|
+
ruling: "D1" | "D2";
|
|
86
|
+
reason: string;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 收编报告。
|
|
90
|
+
*
|
|
91
|
+
* 🔴 **「不可变」只在 `status: "adopted"` 之后成立**(codex 交叉复审 [high],亲读 server
|
|
92
|
+
* `runner.ts` 的 `receiptOf` 验真):终态在 phase 6 一次落库(`report_json`),此后逐字节原样回放 —— 那才是
|
|
93
|
+
* 幂等判据。而 `status: "stalled"` 的回执上**还没有那一行**,server 于是拿**当前行**现场投影出一份同形的
|
|
94
|
+
* 报告(`atMs` = 行的 `updated_at_ms`、configs/legs = 当前列)。所以:
|
|
95
|
+
* · `stalled` 的这一份是**临时投影**,下一次读可能整份都不一样(时刻、腿的行数、配置账全会动);
|
|
96
|
+
* · **别把它当审计凭据落盘** —— 要冻结的那一份,等 `status === "adopted"` 再取。
|
|
97
|
+
* 两种形在类型上同形是 server 的裁定(包络只有一种);判据是 `status`,不是这份对象自身。
|
|
98
|
+
*/
|
|
99
|
+
export interface AdoptionReport {
|
|
100
|
+
adoptionId: string;
|
|
101
|
+
/** 本版只做 form b。显式在场是为了 form a 上车后回执可分辨(下游不必按缺席位推断)。 */
|
|
102
|
+
form: "b";
|
|
103
|
+
from: AdoptionSource;
|
|
104
|
+
toPrincipal: string;
|
|
105
|
+
atMs: number;
|
|
106
|
+
affectedDeploymentConfigs: AdoptionConfigEntry[];
|
|
107
|
+
legs: AdoptionLeg[];
|
|
108
|
+
notMigratedByDesign: AdoptionNotMigrated[];
|
|
109
|
+
}
|
|
110
|
+
/** 现势读数 —— **每次现算**(与 {@link AdoptionReport} 的史实分家)。 */
|
|
111
|
+
export interface AdoptionCurrent {
|
|
112
|
+
/** 配置账里 `witnessedAtMs === null` 的项(`<deployment>:<key>`)。空 = 账已清。 */
|
|
113
|
+
outstandingConfigs: string[];
|
|
114
|
+
/** form b 恒 0(零承运 ⇒ 无拒收行);字段在场是为了 form a 上车时包络不变形。 */
|
|
115
|
+
quarantined: number;
|
|
116
|
+
/**
|
|
117
|
+
* **仍挂在旧身份名下的行数**(每次现算)。
|
|
118
|
+
*
|
|
119
|
+
* 📐 **聚合方式:按表去重,不是逐腿求和**(codex 交叉复审 [medium],亲读 `countResidual` 验真):一张表
|
|
120
|
+
* 一次判定、身份轴取并集 —— 一条同时在 owner 轴 / scope 轴 / 载荷三处带旧身份的行**只算一次**;然后按表
|
|
121
|
+
* 相加。所以**别**拿它去和 `legs[].rows` 对账,对不上是设计而不是 bug。
|
|
122
|
+
*
|
|
123
|
+
* 🔴 `> 0` = **旧身份下可能还有行,或者这次根本没数成** —— 两种都意味着「去查」。它**不是**「这个部署
|
|
124
|
+
* 此刻仍在写」的证明(那是最常见的成因,不是唯一成因),哪怕 `status` 已经是 `adopted`。
|
|
125
|
+
* 每次 **POST**(写动词)会顺带把这些迟到行扫进新身份并重报此数;**GET 不扫**(但会推进在飞的弧,
|
|
126
|
+
* 见 {@link AdoptionResource.get})。
|
|
127
|
+
*
|
|
128
|
+
* ⚠️ **`1` 是一个二义读数**(codex 交叉复审 [medium],亲读 server `residualOf` 验真):数不出来时
|
|
129
|
+
* (计数查询抛错 / 解析失败)server **fail-closed 报 1**,而不是报 0 —— 因为 0 是「一切干净」的字面断言,
|
|
130
|
+
* 它没资格在没数到的时候说。所以 `1` 既可能是「真有一行」,也可能是「这次没数成」,wire 上分不出来;
|
|
131
|
+
* 服务端日志里有 `adoption_residual_count_failed`。判据用法:`> 0` ⇒ **去查**(这正是它的用途);
|
|
132
|
+
* 但**别**拿 `=== 1` 当「恰好剩一行」的事实喂给报表。
|
|
133
|
+
*/
|
|
134
|
+
residualSourceRows: number;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* 收编回执的**唯一包络**(首次成功与一切幂等重跑**同形**;同形不保证同字节,见下)。
|
|
138
|
+
*
|
|
139
|
+
* 🔴 `adoptionId` 在**顶层**(server 发的是 `{adoptionId, ...receipt}`),与 `immutableReport.adoptionId`
|
|
140
|
+
* 同值 —— 不是嵌套两层的同一个字段被漏抄。
|
|
141
|
+
* 🔴 **`status` 是读这份回执的先决判别位**:`adopted` 之后 `immutableReport` 才是冻结的史实;`stalled` 上
|
|
142
|
+
* 它是当前行的**临时投影**(逐字理由见 {@link AdoptionReport} 顶注)。
|
|
143
|
+
*/
|
|
144
|
+
export interface AdoptionReceipt {
|
|
145
|
+
adoptionId: string;
|
|
146
|
+
/** `adopted` = 终态在(此时 {@link immutableReport} 才是冻结的);`stalled` = 在飞(锁被别的副本持着 /
|
|
147
|
+
* 崩溃后尚未续完)。**`rejected` 不在闭集里**(拒一律 typed 409)。 */
|
|
148
|
+
status: "adopted" | "stalled";
|
|
149
|
+
/** ⚠️ 只有 `status === "adopted"` 时它才不可变;`stalled` 上是临时投影,见 {@link AdoptionReport}。 */
|
|
150
|
+
immutableReport: AdoptionReport;
|
|
151
|
+
current: AdoptionCurrent;
|
|
152
|
+
}
|
|
153
|
+
export declare class AdoptionResource {
|
|
154
|
+
private readonly t;
|
|
155
|
+
constructor(t: Transport);
|
|
156
|
+
/** POST /v1/adoption — 发起一次身份收编(operator-only)。
|
|
157
|
+
*
|
|
158
|
+
* 幂等:同参数重跑**不会**开第二次收编;终态之后回放的 `immutableReport` 逐字节恒同,但 `current` 每次
|
|
159
|
+
* 现算 ⇒ 整份回执**没有**逐字节相同的保证(可能相同也可能不同;在飞时报告本身还是临时投影,
|
|
160
|
+
* 见 {@link AdoptionReport})。
|
|
161
|
+
* 并发同参 POST 由
|
|
162
|
+
* `adoption_log.from_principal` 的 UNIQUE 仲裁:恰一行落库,两条连接拿到同一个 `adoptionId`。
|
|
163
|
+
*
|
|
164
|
+
* ── 拒(全部不产出回执)────────────────────────────────────────────────────────────────────────
|
|
165
|
+
* · 409 `adoption.source_already_bound` —— 源已绑到**别的**目的地(二次收编/多租转让,D7 拒);
|
|
166
|
+
* · 409 `adoption.destination_conflict` —— 目的地侧已有与源侧重叠的逻辑键(体里带冲突表族:去清理它们);
|
|
167
|
+
* · 409 `adoption.destination_unrepresentable` —— 目的地身份装不进这次收编会**派生**出来的某个键
|
|
168
|
+
* (典型:memory 的 `proj:` 键越过列宽)⇒ **换一个更短的目的地身份**。与上一条分家的理由就是这个:
|
|
169
|
+
* 运维的动作完全不同,折成一格等于让人猜。
|
|
170
|
+
* 三条都是 {@link import("../errors.js").ConflictError},按 `errorCode` 分支(status 分不出来)。
|
|
171
|
+
* · 403 `auth.operator_only`;501 `capability.adoption_store_required`(无 SQL 后端);
|
|
172
|
+
* 400 `request.field_invalid`(同名 / principal 装不进某根被写列)。 */
|
|
173
|
+
start(body: AdoptionRequest, opts?: {
|
|
174
|
+
signal?: AbortSignal;
|
|
175
|
+
}): Promise<AdoptionReceipt>;
|
|
176
|
+
/**
|
|
177
|
+
* GET /v1/adoption/:id — 读一次收编的状态。
|
|
178
|
+
*
|
|
179
|
+
* 🔴 **不是一次无副作用的读**(codex 交叉复审 [high],亲读 server `src/adoption/runner.ts` 的 `get()`
|
|
180
|
+
* 验真):行**已终态**(`adopted` / 已拒)⇒ 纯读;行**在飞**(典型:崩溃之后再没人发过 POST 的部署)
|
|
181
|
+
* ⇒ 这条读面会**顺手把弧推完** —— 与 boot 扫描同一条 `driveUnderLock`,会推进 phase、改身份轴上的行、
|
|
182
|
+
* 写配置账、落终态。server 是**故意**这么设计的(否则一次崩溃就得靠人再发一次 POST),但消费端必须
|
|
183
|
+
* 知道这件事:
|
|
184
|
+
* · 别把它当「安全的预取 / 看板轮询」—— 对一条在飞的弧,读一次就等于替它按下继续;
|
|
185
|
+
* · 与 POST 的真差别只有一条:GET **不扫**迟到行(`sweep=false`),POST 扫;
|
|
186
|
+
* · 重复调用是安全的(advisory 锁 + phase CAS + 幂等身份 ⇒ 重放与调用一次同果),所以 SDK 对 GET 的
|
|
187
|
+
* 自动重试不引入新风险 —— 但「安全地重放一个会推进状态的动作」不等于「这是一次只读」。
|
|
188
|
+
* 想要一次**保证零推进**的观察,今天 wire 上没有那个动词 —— 不要用注释假装有。
|
|
189
|
+
*
|
|
190
|
+
* 404 `not_found.adoption`(→ {@link import("../errors.js").NotFoundError})= 没有这个 id。
|
|
191
|
+
* ⚠️ 被拒的收编在这条路上同样是 typed 409,不是 404:拒的事实是**记着**的。 */
|
|
192
|
+
get(adoptionId: string, opts?: {
|
|
193
|
+
signal?: AbortSignal;
|
|
194
|
+
}): Promise<AdoptionReceipt>;
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=adoption.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adoption.d.ts","sourceRoot":"","sources":["../../src/resources/adoption.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export class AdoptionResource {
|
|
2
|
+
t;
|
|
3
|
+
constructor(t) {
|
|
4
|
+
this.t = t;
|
|
5
|
+
}
|
|
6
|
+
/** POST /v1/adoption — 发起一次身份收编(operator-only)。
|
|
7
|
+
*
|
|
8
|
+
* 幂等:同参数重跑**不会**开第二次收编;终态之后回放的 `immutableReport` 逐字节恒同,但 `current` 每次
|
|
9
|
+
* 现算 ⇒ 整份回执**没有**逐字节相同的保证(可能相同也可能不同;在飞时报告本身还是临时投影,
|
|
10
|
+
* 见 {@link AdoptionReport})。
|
|
11
|
+
* 并发同参 POST 由
|
|
12
|
+
* `adoption_log.from_principal` 的 UNIQUE 仲裁:恰一行落库,两条连接拿到同一个 `adoptionId`。
|
|
13
|
+
*
|
|
14
|
+
* ── 拒(全部不产出回执)────────────────────────────────────────────────────────────────────────
|
|
15
|
+
* · 409 `adoption.source_already_bound` —— 源已绑到**别的**目的地(二次收编/多租转让,D7 拒);
|
|
16
|
+
* · 409 `adoption.destination_conflict` —— 目的地侧已有与源侧重叠的逻辑键(体里带冲突表族:去清理它们);
|
|
17
|
+
* · 409 `adoption.destination_unrepresentable` —— 目的地身份装不进这次收编会**派生**出来的某个键
|
|
18
|
+
* (典型:memory 的 `proj:` 键越过列宽)⇒ **换一个更短的目的地身份**。与上一条分家的理由就是这个:
|
|
19
|
+
* 运维的动作完全不同,折成一格等于让人猜。
|
|
20
|
+
* 三条都是 {@link import("../errors.js").ConflictError},按 `errorCode` 分支(status 分不出来)。
|
|
21
|
+
* · 403 `auth.operator_only`;501 `capability.adoption_store_required`(无 SQL 后端);
|
|
22
|
+
* 400 `request.field_invalid`(同名 / principal 装不进某根被写列)。 */
|
|
23
|
+
async start(body, opts) {
|
|
24
|
+
return this.t.request({
|
|
25
|
+
method: "POST",
|
|
26
|
+
path: "/v1/adoption",
|
|
27
|
+
body,
|
|
28
|
+
signal: opts?.signal,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* GET /v1/adoption/:id — 读一次收编的状态。
|
|
33
|
+
*
|
|
34
|
+
* 🔴 **不是一次无副作用的读**(codex 交叉复审 [high],亲读 server `src/adoption/runner.ts` 的 `get()`
|
|
35
|
+
* 验真):行**已终态**(`adopted` / 已拒)⇒ 纯读;行**在飞**(典型:崩溃之后再没人发过 POST 的部署)
|
|
36
|
+
* ⇒ 这条读面会**顺手把弧推完** —— 与 boot 扫描同一条 `driveUnderLock`,会推进 phase、改身份轴上的行、
|
|
37
|
+
* 写配置账、落终态。server 是**故意**这么设计的(否则一次崩溃就得靠人再发一次 POST),但消费端必须
|
|
38
|
+
* 知道这件事:
|
|
39
|
+
* · 别把它当「安全的预取 / 看板轮询」—— 对一条在飞的弧,读一次就等于替它按下继续;
|
|
40
|
+
* · 与 POST 的真差别只有一条:GET **不扫**迟到行(`sweep=false`),POST 扫;
|
|
41
|
+
* · 重复调用是安全的(advisory 锁 + phase CAS + 幂等身份 ⇒ 重放与调用一次同果),所以 SDK 对 GET 的
|
|
42
|
+
* 自动重试不引入新风险 —— 但「安全地重放一个会推进状态的动作」不等于「这是一次只读」。
|
|
43
|
+
* 想要一次**保证零推进**的观察,今天 wire 上没有那个动词 —— 不要用注释假装有。
|
|
44
|
+
*
|
|
45
|
+
* 404 `not_found.adoption`(→ {@link import("../errors.js").NotFoundError})= 没有这个 id。
|
|
46
|
+
* ⚠️ 被拒的收编在这条路上同样是 typed 409,不是 404:拒的事实是**记着**的。 */
|
|
47
|
+
async get(adoptionId, opts) {
|
|
48
|
+
return this.t.request({
|
|
49
|
+
method: "GET",
|
|
50
|
+
path: `/v1/adoption/${encodeURIComponent(adoptionId)}`,
|
|
51
|
+
signal: opts?.signal,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=adoption.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adoption.js","sourceRoot":"","sources":["../../src/resources/adoption.ts"],"names":[],"mappings":"AAyKA,MAAM,OAAO,gBAAgB;IACE;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C;;;;;;;;;;;;;;;;kEAgB8D;IAC9D,KAAK,CAAC,KAAK,CAAC,IAAqB,EAAE,IAA+B;QAChE,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAkB;YACrC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,cAAc;YACpB,IAAI;YACJ,MAAM,EAAE,IAAI,EAAE,MAAM;SACrB,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;;;yDAeqD;IACrD,KAAK,CAAC,GAAG,CAAC,UAAkB,EAAE,IAA+B;QAC3D,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAkB;YACrC,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,gBAAgB,kBAAkB,CAAC,UAAU,CAAC,EAAE;YACtD,MAAM,EAAE,IAAI,EAAE,MAAM;SACrB,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rules — **持久权限规则**的导入面(#154 车二 / design/179 §7;server `src/http/routes/rules.ts`)。
|
|
3
|
+
*
|
|
4
|
+
* `ccImportPrepare(layers)` → POST /v1/rules/cc-import/prepare — 读交上来的 CC settings 层,回**预览** +
|
|
5
|
+
* 一张一次性票(还没有任何规则落库)
|
|
6
|
+
* `ccImportRedeem(ticket)` → POST /v1/rules/cc-import/redeem — 原子消费票 → 确认 → 批量兑付进店
|
|
7
|
+
*
|
|
8
|
+
* 🔴 **两步不是仪式,是同意协议的形**:第一步只产生「如果确认会发生什么」的预览;只有第二步够得着写面。
|
|
9
|
+
* 中间那张票是 **principal 绑定 / 有期(10 分钟)/ 一次性原子消费 / 载荷绑定** 的 —— 它不是可缓存的凭据,
|
|
10
|
+
* 也不该跨用户传递。
|
|
11
|
+
*
|
|
12
|
+
* ⚠️ **prepare 不是零写入、也不幂等**(codex 交叉复审 [medium],亲读 server `rules-consent.ts` 验真):
|
|
13
|
+
* 没有任何**规则**落库,但每一次成功的 prepare 都会落一条 **pending 审批记录**并**再铸一张有效票**。
|
|
14
|
+
* 所以别把它当可随手重放的预览接口:预览一次、呈给人看、然后兑付或丢弃。(超候选帽的拒绝会 best-effort
|
|
15
|
+
* 收掉刚落的那条记录 —— 收不掉只是留一条不影响任何判决的孤儿行,但那也不是「零残留」的承诺。)
|
|
16
|
+
*
|
|
17
|
+
* 🔴 **lane = principal,不是 operator**:用户导的是**他自己**的规则,一条规则的语义就是「这个人自己说过
|
|
18
|
+
* yes」。运维在这条路上没有位置(他既不该替租户扩权,也不该被要求代人点确认);一个 operator 要给自己
|
|
19
|
+
* 导规则,用他自己的 principal 走同一条路即可。
|
|
20
|
+
*
|
|
21
|
+
* 🔴 **只读 allow 桶**:deny/ask 桶是**收紧**方向,有自己的通道 —— 从一条放松的车道导进来是走错门。
|
|
22
|
+
* 预览的 `uncovered` 把「本版没读的两层」写进 TYPE(两键记录,不是列表):一份只报了自己读过的层的预览,
|
|
23
|
+
* 是在冒充它没有的完整性。
|
|
24
|
+
*
|
|
25
|
+
* 🔴 **redeem 的 404 是同形的**:伪造的票 / 别人的票 / 过期 / 已用过 —— 四个票面成因在 wire 上**一个字都
|
|
26
|
+
* 不差**(返回不同的码就是一台存在性 oracle)。⚠️ 而且它**不止**这四类:记录不见了、载荷摘要对不上、
|
|
27
|
+
* 确认步的裁定性拒绝 —— 这些「服务端状态/完整性」失败**也**折进同一个 404。所以 404 的含义只有一句
|
|
28
|
+
* 「这张票在这里不可用,重来一遍」,**禁按成因分支**,也别把它一律读成「用户拿错票了」(分类只进服务端
|
|
29
|
+
* 日志)。唯一可分的是 503 `state.rule_import_retry`(→ {@link import("../errors.js").ServiceStateError}):
|
|
30
|
+
* 那一支意味着**票还在**,原样重试即可,与「这张票没了」是相反的处置。
|
|
31
|
+
*
|
|
32
|
+
* 🔴 **部署位:整条车道默认关**(server `PERMISSION_RULES_ENABLED` 默认 false)+ 需真装配规则店 ——
|
|
33
|
+
* 缺一 ⇒ 两口都 501 `capability.rule_store_required`(→
|
|
34
|
+
* {@link import("../errors.js").CapabilityUnavailableError}),同一条谓词也让审批帧上不带 `ruleSuggestions`。
|
|
35
|
+
* `/v1/capabilities` 上**今天没有**这一族的能力位,所以壳只能按「面在不在」渲染:发一次看 501,或读帧上有没有
|
|
36
|
+
* 候选 —— 别按 server 版本号猜。
|
|
37
|
+
*/
|
|
38
|
+
import type { Transport } from "../transport.js";
|
|
39
|
+
/** 本版读的三个用户可编辑 settings 层(core `ImportedSettingsLayer`)。 */
|
|
40
|
+
export type CcImportSettingsLayer = "userSettings" | "projectSettings" | "localSettings";
|
|
41
|
+
/** 一条持久规则的作用域(core `RuleScope`)。`project` 的 `root` 是这条规则将来在哪些 cwd 下生效的前缀。 */
|
|
42
|
+
export type RuleScope = {
|
|
43
|
+
kind: "global";
|
|
44
|
+
} | {
|
|
45
|
+
kind: "project";
|
|
46
|
+
root: string;
|
|
47
|
+
};
|
|
48
|
+
/** 一条候选规则:规范文本 + 它会落在哪个作用域(core `RuleCandidate`)。 */
|
|
49
|
+
export interface RuleCandidate {
|
|
50
|
+
rule: string;
|
|
51
|
+
scope: RuleScope;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 一条没进候选的条目。
|
|
55
|
+
*
|
|
56
|
+
* 🔴 **`reason` 是给人看的散文,不是机读码**(codex 交叉复审 [medium],亲读 core `prepareCcImport` 验真):
|
|
57
|
+
* 真值形有三种 —— 语法拒是 `` `${code}: ${message}` ``(**前缀**是 `RuleRejectCode`,如
|
|
58
|
+
* `"invalid.bare_interpreter_prefix: …"`,不是裸码)、整层 JSON 解不开是
|
|
59
|
+
* `` `settings file is not valid JSON (${err})` ``、条目不是串是 `"settings entry is not a string"`。
|
|
60
|
+
* 想分类就**只**按 `:` 前那截前缀,而且要容得下没有前缀的两种;别做全串等值匹配,更别指望裸码。
|
|
61
|
+
*
|
|
62
|
+
* ⚠️ `rule` 也不总是一条规则文本:整层 JSON 解不开的那一支,这里放的是**那一层的 path**(条目还没解析出来,
|
|
63
|
+
* 没有规则可放)。渲染时别假定它一定是 `Bash(...)` 形。
|
|
64
|
+
*/
|
|
65
|
+
export interface CcImportSkippedRule {
|
|
66
|
+
rule: string;
|
|
67
|
+
reason: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 预览里的逐层读取报告。
|
|
71
|
+
*
|
|
72
|
+
* ⚠️ **在这条 HTTP 路上 `found` 恒 `true`**(codex 交叉复审 [medium],亲读验真):core 只在它那个注入的
|
|
73
|
+
* 读口返回 `undefined` 或抛错时才写 `false`,而 server 的适配器把请求体里**必填**的 `content` 原样交回去
|
|
74
|
+
* ⇒ 永不缺席。空文本、`{}`、没有 allow 桶都照样是 `found: true`(它们只是不产候选)。所以**别**把
|
|
75
|
+
* `found` 当「这一层有没有规则」的判据 —— 那要看 `candidates` 里有没有这一层作用域的条目。
|
|
76
|
+
* 字段保留是因为它是 core 预览形的一部分(别的宿主用真文件系统读口时它才有判别力)。
|
|
77
|
+
*/
|
|
78
|
+
export interface CcImportLayerReport {
|
|
79
|
+
path: string;
|
|
80
|
+
layer: CcImportSettingsLayer;
|
|
81
|
+
found: boolean;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* 一层交上来的 settings(server 侧 zod 是 `.strict()` —— 多一个键 = 400,把 `content` 拼成 `contents`
|
|
85
|
+
* 的客户端应当场知道,而不是拿到一份「零候选」的预览去纳闷)。
|
|
86
|
+
*
|
|
87
|
+
* 🔴 `root` **非空是硬的**:`root: ""` 在 core 里会变成 `{kind:"project", root:""}`,而空前缀**包含每一个
|
|
88
|
+
* cwd** —— 一条项目内规则就此悄悄升成全局规则。server 侧当场 400。
|
|
89
|
+
* ⚠️ `root` 的**真实性**不校验:云端 server 上没有那棵树可对照,假装校验过才是谎;它只是「这条规则在哪些
|
|
90
|
+
* cwd 下生效」的用户自陈标签。
|
|
91
|
+
* 上限:单层 `content` ≤ 16 KiB,`layers` 一次 1–3 层(超出 ⇒ 400 / 413)。
|
|
92
|
+
*/
|
|
93
|
+
export interface CcImportLayer {
|
|
94
|
+
layer: CcImportSettingsLayer;
|
|
95
|
+
path: string;
|
|
96
|
+
root: string;
|
|
97
|
+
content: string;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* 导入**会做什么**(在任何人确认之前)。
|
|
101
|
+
*
|
|
102
|
+
* `uncovered` 是**两键记录而不是列表**(core 原形):本版不读的两层写在 TYPE 里,于是「空列表 / 少一员 /
|
|
103
|
+
* 重复一员」都不可拼写。
|
|
104
|
+
*/
|
|
105
|
+
export interface CcImportPreview {
|
|
106
|
+
/** 会被持久化的候选(顺序即兑付顺序)。 */
|
|
107
|
+
candidates: RuleCandidate[];
|
|
108
|
+
/** 没进候选的条目(`reason` 是散文,不是码 —— 见 {@link CcImportSkippedRule})。 */
|
|
109
|
+
skipped: CcImportSkippedRule[];
|
|
110
|
+
/** 逐层读取报告。 */
|
|
111
|
+
layers: CcImportLayerReport[];
|
|
112
|
+
/** 本版**不读**的两层,写死在类型里(不是运行期列表)。 */
|
|
113
|
+
uncovered: {
|
|
114
|
+
flagSettings: "not-imported-v1";
|
|
115
|
+
policySettings: "not-imported-v1";
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/** `prepare` 的 200 体。**此刻还没有任何规则落库** —— 落库要等 `redeem`;但 pending 记录与这张票已经是
|
|
119
|
+
* durable 的(prepare 不幂等,见模块顶注)。 */
|
|
120
|
+
export interface CcImportPrepareResult {
|
|
121
|
+
preview: CcImportPreview;
|
|
122
|
+
/** 一次性、principal 绑定、有期、载荷绑定的兑付票。不可缓存复用,不该跨用户传递。 */
|
|
123
|
+
ticket: string;
|
|
124
|
+
/** 票的绝对过期时刻(server 时钟毫秒;窗 = 10 分钟)。 */
|
|
125
|
+
expiresAtMs: number;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* 导入**真做了什么** —— 与预览是**不同时刻、不同契约**(去重、并发、兑付期校验都可能让一条在两者之间
|
|
129
|
+
* 换位置)。
|
|
130
|
+
*
|
|
131
|
+
* ⚠️ `skippedAtRedeem` 在本车道的成功臂上恒为空:server 把「非空」一律当**不确定**处理并放回认领
|
|
132
|
+
* (于是你看到的是 503 可重试,而不是一个「一半没落地」的 200)。它留在形上是为了 core 契约同形。
|
|
133
|
+
*/
|
|
134
|
+
export interface CcImportResult {
|
|
135
|
+
/** 本次真落库的规则。 */
|
|
136
|
+
persisted: RuleCandidate[];
|
|
137
|
+
/** 已经在店里、这次不重复添加的(不是失败)。 */
|
|
138
|
+
deduped: RuleCandidate[];
|
|
139
|
+
/** 兑付期被逐条拒绝的。 */
|
|
140
|
+
skippedAtRedeem: CcImportSkippedRule[];
|
|
141
|
+
/** 规则店的单调修订号(兑付后的读数)。 */
|
|
142
|
+
rev: number;
|
|
143
|
+
}
|
|
144
|
+
/** `redeem` 的 200 体。 */
|
|
145
|
+
export interface CcImportRedeemResult {
|
|
146
|
+
result: CcImportResult;
|
|
147
|
+
}
|
|
148
|
+
export declare class RulesResource {
|
|
149
|
+
private readonly t;
|
|
150
|
+
constructor(t: Transport);
|
|
151
|
+
/** POST /v1/rules/cc-import/prepare — 交 1–3 层 CC settings,拿**预览 + 一张票**(零规则落库,但**有**
|
|
152
|
+
* durable 副作用:一条 pending 记录 + 一张票 ⇒ 不幂等,别循环重放,见模块顶注)。
|
|
153
|
+
*
|
|
154
|
+
* 典型用法:壳读用户机器上的 `~/.claude/settings.json` / `<repo>/.claude/settings.json` /
|
|
155
|
+
* `<repo>/.claude/settings.local.json`,把**内容**交上来(云端 server 上没有用户的文件系统 —— 这是部署形,
|
|
156
|
+
* 不是绕过:读的仍然只有 allow 桶)。把 `preview.candidates` 呈给人看,人点确认再调 {@link ccImportRedeem}。
|
|
157
|
+
*
|
|
158
|
+
* 413 `request.payload_too_large`(→ {@link import("../errors.js").PayloadTooLargeError})= 全部层合计候选
|
|
159
|
+
* 超上限(200 条):**缩短后重发**,重试同一份没有意义。501 = 本部署没接规则店。 */
|
|
160
|
+
ccImportPrepare(layers: CcImportLayer[], opts?: {
|
|
161
|
+
signal?: AbortSignal;
|
|
162
|
+
}): Promise<CcImportPrepareResult>;
|
|
163
|
+
/** POST /v1/rules/cc-import/redeem — 用 {@link ccImportPrepare} 给的票原子兑付整批。
|
|
164
|
+
*
|
|
165
|
+
* 🔴 **不是 submit 类,SDK 不自动重试**:票是一次性消费的,一次自动重放就等于把人的确认烧掉两次。
|
|
166
|
+
* 要重试请**自己**在拿到 503 `state.rule_import_retry` 之后重发(那一支明说票还在;体里 `retryAfterSec`
|
|
167
|
+
* 与 `Retry-After` 同值)。
|
|
168
|
+
* 🔴 404 `not_found.rule_ticket` 是一个**同形信封**:四类票面拒绝(伪造/别人的/过期/已用过)**加上**
|
|
169
|
+
* 非可重试的记录/载荷失败(记录不见了、载荷摘要对不上、确认步裁定性拒绝)全折在这一格。按它一丢了之
|
|
170
|
+
* 即可 —— 别试图分辨成因(wire 上分不出来是设计),也别把它一律读成「用户拿错票了」。 */
|
|
171
|
+
ccImportRedeem(ticket: string, opts?: {
|
|
172
|
+
signal?: AbortSignal;
|
|
173
|
+
}): Promise<CcImportRedeemResult>;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/resources/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,4DAA4D;AAC5D,MAAM,MAAM,qBAAqB,GAAG,cAAc,GAAG,iBAAiB,GAAG,eAAe,CAAC;AAEzF,6EAA6E;AAC7E,MAAM,MAAM,SAAS,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/E,qDAAqD;AACrD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,SAAS,CAAC;CAClB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,qBAAqB,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,qBAAqB,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,yBAAyB;IACzB,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,kEAAkE;IAClE,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,cAAc;IACd,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,mCAAmC;IACnC,SAAS,EAAE;QAAE,YAAY,EAAE,iBAAiB,CAAC;QAAC,cAAc,EAAE,iBAAiB,CAAA;KAAE,CAAC;CACnF;AAED;oCACoC;AACpC,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,eAAe,CAAC;IACzB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,gBAAgB;IAChB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,4BAA4B;IAC5B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,iBAAiB;IACjB,eAAe,EAAE,mBAAmB,EAAE,CAAC;IACvC,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAwB;AACxB,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC;;;;;;;;yDAQqD;IAC/C,eAAe,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAS/G;;;;;;;yDAOqD;IAC/C,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAQrG"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export class RulesResource {
|
|
2
|
+
t;
|
|
3
|
+
constructor(t) {
|
|
4
|
+
this.t = t;
|
|
5
|
+
}
|
|
6
|
+
/** POST /v1/rules/cc-import/prepare — 交 1–3 层 CC settings,拿**预览 + 一张票**(零规则落库,但**有**
|
|
7
|
+
* durable 副作用:一条 pending 记录 + 一张票 ⇒ 不幂等,别循环重放,见模块顶注)。
|
|
8
|
+
*
|
|
9
|
+
* 典型用法:壳读用户机器上的 `~/.claude/settings.json` / `<repo>/.claude/settings.json` /
|
|
10
|
+
* `<repo>/.claude/settings.local.json`,把**内容**交上来(云端 server 上没有用户的文件系统 —— 这是部署形,
|
|
11
|
+
* 不是绕过:读的仍然只有 allow 桶)。把 `preview.candidates` 呈给人看,人点确认再调 {@link ccImportRedeem}。
|
|
12
|
+
*
|
|
13
|
+
* 413 `request.payload_too_large`(→ {@link import("../errors.js").PayloadTooLargeError})= 全部层合计候选
|
|
14
|
+
* 超上限(200 条):**缩短后重发**,重试同一份没有意义。501 = 本部署没接规则店。 */
|
|
15
|
+
async ccImportPrepare(layers, opts) {
|
|
16
|
+
return this.t.request({
|
|
17
|
+
method: "POST",
|
|
18
|
+
path: "/v1/rules/cc-import/prepare",
|
|
19
|
+
body: { layers },
|
|
20
|
+
signal: opts?.signal,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/** POST /v1/rules/cc-import/redeem — 用 {@link ccImportPrepare} 给的票原子兑付整批。
|
|
24
|
+
*
|
|
25
|
+
* 🔴 **不是 submit 类,SDK 不自动重试**:票是一次性消费的,一次自动重放就等于把人的确认烧掉两次。
|
|
26
|
+
* 要重试请**自己**在拿到 503 `state.rule_import_retry` 之后重发(那一支明说票还在;体里 `retryAfterSec`
|
|
27
|
+
* 与 `Retry-After` 同值)。
|
|
28
|
+
* 🔴 404 `not_found.rule_ticket` 是一个**同形信封**:四类票面拒绝(伪造/别人的/过期/已用过)**加上**
|
|
29
|
+
* 非可重试的记录/载荷失败(记录不见了、载荷摘要对不上、确认步裁定性拒绝)全折在这一格。按它一丢了之
|
|
30
|
+
* 即可 —— 别试图分辨成因(wire 上分不出来是设计),也别把它一律读成「用户拿错票了」。 */
|
|
31
|
+
async ccImportRedeem(ticket, opts) {
|
|
32
|
+
return this.t.request({
|
|
33
|
+
method: "POST",
|
|
34
|
+
path: "/v1/rules/cc-import/redeem",
|
|
35
|
+
body: { ticket },
|
|
36
|
+
signal: opts?.signal,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/resources/rules.ts"],"names":[],"mappings":"AAsJA,MAAM,OAAO,aAAa;IACK;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;IAE7C;;;;;;;;yDAQqD;IACrD,KAAK,CAAC,eAAe,CAAC,MAAuB,EAAE,IAA+B;QAC5E,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAwB;YAC3C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,6BAA6B;YACnC,IAAI,EAAE,EAAE,MAAM,EAAE;YAChB,MAAM,EAAE,IAAI,EAAE,MAAM;SACrB,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;yDAOqD;IACrD,KAAK,CAAC,cAAc,CAAC,MAAc,EAAE,IAA+B;QAClE,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAuB;YAC1C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,4BAA4B;YAClC,IAAI,EAAE,EAAE,MAAM,EAAE;YAChB,MAAM,EAAE,IAAI,EAAE,MAAM;SACrB,CAAC,CAAC;IACL,CAAC;CACF"}
|