@sema-agent/sdk 8.6.0 → 8.8.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/README.md +77 -3
- package/dist/health.d.ts +17 -0
- package/dist/health.d.ts.map +1 -1
- package/dist/health.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/resources/rules.d.ts +85 -8
- package/dist/resources/rules.d.ts.map +1 -1
- package/dist/resources/rules.js +9 -1
- package/dist/resources/rules.js.map +1 -1
- package/dist/resources/tool-approvals.d.ts +7 -3
- package/dist/resources/tool-approvals.d.ts.map +1 -1
- package/dist/resources/tool-approvals.js.map +1 -1
- package/dist/types.d.ts +68 -7
- package/dist/types.d.ts.map +1 -1
- package/openapi.yaml +243 -31
- package/package.json +1 -1
package/openapi.yaml
CHANGED
|
@@ -4620,10 +4620,18 @@ paths:
|
|
|
4620
4620
|
x-status: gated # server routes/rules.ts handleRuleList;同 cc-import 的部署谓词。SDK rules.list() 消费。
|
|
4621
4621
|
summary: List the rules that are LIVE under a principal (keyset-paged, cursor bound to the revision).
|
|
4622
4622
|
description: >
|
|
4623
|
-
List the persisted
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4623
|
+
List the persisted rules currently live under one principal (tombstones already folded) — all THREE
|
|
4624
|
+
behaviors from server >= 7.67.0, not the allow bucket alone.
|
|
4625
|
+
Ordering is deterministic — `(scope, rule, behavior)` lexicographic from server >= 7.67.0, `(scope, rule)`
|
|
4626
|
+
before it — because keyset paging's whole premise is that the same data comes back in the same order every
|
|
4627
|
+
time. The order is decided by the server, NOT by the store (core's `list()` promises none).
|
|
4628
|
+
|
|
4629
|
+
🔴 THE CURSOR CARRIES A FORMAT GENERATION, BUMPED TO v2 IN 7.67.0 (the sort key gained `behavior`, since a
|
|
4630
|
+
same-text deny/allow pair collided under the old two-part key and the strict `>` silently dropped the
|
|
4631
|
+
sibling row at a page boundary). During a rolling upgrade or rollback the two generations REFUSE each
|
|
4632
|
+
other's cursors with a 400 rather than each walking its own key shape — a governance listing going wrong
|
|
4633
|
+
under an all-200 conversation is far more expensive than one re-listing. The cursor stays OPAQUE and the
|
|
4634
|
+
handling is unchanged: echo it back verbatim, and on a 400 drop it and re-list from the top.
|
|
4627
4635
|
|
|
4628
4636
|
🔴 THE CURSOR IS BOUND TO `(rev, principal, scope)` AND A MISMATCH IS REFUSED, NOT RESET. A rule set
|
|
4629
4637
|
is read WHOLE, so there is no tearing WITHIN a page — tearing happens BETWEEN pages, when somebody
|
|
@@ -4688,12 +4696,16 @@ paths:
|
|
|
4688
4696
|
tags: [rules]
|
|
4689
4697
|
operationId: rulesRevoke
|
|
4690
4698
|
x-status: gated # server routes/rules.ts handleRuleRevoke;同 cc-import 的部署谓词。SDK rules.revoke() 消费。
|
|
4691
|
-
summary: Revoke a persisted rule BY CONTENT — `(rule, scope)`, with no id in the path.
|
|
4699
|
+
summary: Revoke a persisted rule BY CONTENT — `(behavior, rule, scope)`, with no id in the path.
|
|
4692
4700
|
description: >
|
|
4693
|
-
Revoke one persisted
|
|
4694
|
-
path segment on purpose: a rule's identity IS that
|
|
4695
|
-
`removePersistedRule` primitive (which this endpoint always goes
|
|
4696
|
-
form over the add dots.
|
|
4701
|
+
Revoke one persisted rule identified by its CONTENT triple `(behavior, rule, scope)` — a pair before
|
|
4702
|
+
server 7.67.0. There is no `:id` path segment on purpose: a rule's identity IS that triple, the server
|
|
4703
|
+
mints no row id, and the engine's `removePersistedRule` primitive (which this endpoint always goes
|
|
4704
|
+
through) works in observed-remove form over the add dots.
|
|
4705
|
+
|
|
4706
|
+
🔴 `behavior` IS REQUIRED AND HAS NO DEFAULT (server >= 7.67.0; omitting it is a 400
|
|
4707
|
+
`request.body_shape`). Defaulting it would let a revoke aimed at an `allow` delete the same-text `deny` —
|
|
4708
|
+
a refusal the operator meant to keep — while answering 200.
|
|
4697
4709
|
|
|
4698
4710
|
🔴 IDEMPOTENT, AND DELIBERATELY NOT A 404. Revoking twice, or revoking something that was never
|
|
4699
4711
|
there, is `200 {status:"no-op"}` — a "did this rule ever exist?" 404 would be an existence oracle
|
|
@@ -4725,7 +4737,7 @@ paths:
|
|
|
4725
4737
|
content:
|
|
4726
4738
|
application/json:
|
|
4727
4739
|
schema: { $ref: '#/components/schemas/RuleRevokeResult' }
|
|
4728
|
-
'400': { $ref: '#/components/responses/BadRequest' } # request.body_shape — body is not {rule, scope, principal?}, or `scope` is not `global`/`project:<non-empty root>`
|
|
4740
|
+
'400': { $ref: '#/components/responses/BadRequest' } # request.body_shape — body is not {behavior, rule, scope, principal?} (server >= 7.67.0: `behavior` is REQUIRED and has no default), or `scope` is not `global`/`project:<non-empty root>`
|
|
4729
4741
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
4730
4742
|
'403': { $ref: '#/components/responses/Forbidden' } # auth.operator_only — revoking another principal's rule without explicit OPERATOR_PRINCIPALS membership
|
|
4731
4743
|
'429': { $ref: '#/components/responses/RateLimited' }
|
|
@@ -7169,6 +7181,39 @@ components:
|
|
|
7169
7181
|
note:
|
|
7170
7182
|
type: string
|
|
7171
7183
|
|
|
7184
|
+
PostureKnobReading:
|
|
7185
|
+
type: object
|
|
7186
|
+
additionalProperties: false
|
|
7187
|
+
description: >
|
|
7188
|
+
server >= 7.67.0 (S-178) — ONE deployment knob's reading: its value, WHO SET IT, and one operator-facing
|
|
7189
|
+
pointer. Same shape as `ReadFacePosture`, whose value key is called `face` instead of `value`; both exist,
|
|
7190
|
+
neither replaces the other.
|
|
7191
|
+
|
|
7192
|
+
🔴 WHY NOT A BARE VALUE: a bare boolean or number cannot answer "why is THIS machine on this setting, and
|
|
7193
|
+
how do I pin it back". From 7.67.0 a single-user turnkey worker (REQUIRE_PRINCIPAL unset) derives
|
|
7194
|
+
`DURABLE_APPROVAL` ON and a 24h approval window when neither is set, so a default FLIP has to be visible
|
|
7195
|
+
on an operator surface or nobody sees it.
|
|
7196
|
+
|
|
7197
|
+
`source` is the CLOSED four-word set (exhaustive switch on the server — adding a word is a compile error
|
|
7198
|
+
there), in PRECEDENCE order: `env` = pinned by this machine's env var (deployment sovereignty; beats any
|
|
7199
|
+
published value) · `center` = applied from the config-center (restart-to-apply) · `posture` = derived from
|
|
7200
|
+
the deployment shape (single-user turnkey) · `engine-default` = nothing pinned, the built-in default is in
|
|
7201
|
+
force. Only `env`/`center` count as "an operator asked for this"; a posture-derived `true` does not.
|
|
7202
|
+
`note` is PROSE for a human (per-knob, and on the `posture` arm it is that knob's own fact sentence) —
|
|
7203
|
+
classify on `source`, never by matching `note`.
|
|
7204
|
+
|
|
7205
|
+
🔴 `value` IS NARROWED AT THE REFERENCE POINT, not here: the reading is one shape over many knobs, and a
|
|
7206
|
+
second copy of the record per value type is how the three keys drift apart. Each `serverGates` row pins
|
|
7207
|
+
its own `value` type beside the `$ref`.
|
|
7208
|
+
required: [value, source, note]
|
|
7209
|
+
properties:
|
|
7210
|
+
value:
|
|
7211
|
+
description: 'The knob''s effective value. Typed by the referencing site (boolean / integer / …).'
|
|
7212
|
+
source:
|
|
7213
|
+
type: string
|
|
7214
|
+
enum: [env, center, posture, engine-default]
|
|
7215
|
+
note: { type: string }
|
|
7216
|
+
|
|
7172
7217
|
SkillSpec:
|
|
7173
7218
|
type: object
|
|
7174
7219
|
description: A per-request skill (passed as an object; core-native TaskSpec.skills shape).
|
|
@@ -9568,12 +9613,16 @@ components:
|
|
|
9568
9613
|
DeniedBy:
|
|
9569
9614
|
type: string
|
|
9570
9615
|
description: >
|
|
9571
|
-
WHO REFUSED a call — the LAYER whose verdict is the deny (core
|
|
9572
|
-
CLOSED). The other question a deny raises — who ASKED — is
|
|
9573
|
-
share one seven-word list in which `classifier` meant both.
|
|
9616
|
+
WHO REFUSED a call — the LAYER whose verdict is the deny (core `DENIED_BY_VALUES`; 8 words in 7.6.0,
|
|
9617
|
+
NINE from core 7.9.0 / server >= 7.67.0, CLOSED). The other question a deny raises — who ASKED — is
|
|
9618
|
+
answered by `AskOrigin`; the two used to share one seven-word list in which `classifier` meant both.
|
|
9574
9619
|
`policy` = the deployment `ToolPolicy` denied (directly, or re-checking an approved edit), or the
|
|
9575
9620
|
approval-edit chain hit its round cap · `hook` = a PreToolUse hook denied, threw, or never answered ·
|
|
9576
|
-
`org` = an organization policy rule denied · `
|
|
9621
|
+
`org` = an organization policy rule denied · `persisted_rule` = the person's OWN standing `deny` row
|
|
9622
|
+
denied (the deny list of their settings, imported — reachable from core 7.9.0 #625's three-behavior
|
|
9623
|
+
persisted rules). It is the personal-store sibling of `org`: same VETO family (it can overturn an approval
|
|
9624
|
+
a person already gave, and it re-judges an edited command), which is why it is neither `policy` nor
|
|
9625
|
+
`ask_resolution` · `classifier` = the auto-mode classifier denied directly ·
|
|
9577
9626
|
`plan_mode` = plan mode's read-only block on a write tool · `compliance` = the compliance call-time
|
|
9578
9627
|
lock · `write_protection` = an approved edit was rewritten onto a write-protected path no approval
|
|
9579
9628
|
covers · `ask_resolution` = the ask's own settlement IS the refusal (detail on `GateOutcome.settlement`).
|
|
@@ -9582,7 +9631,7 @@ components:
|
|
|
9582
9631
|
record WHOLE (report + withhold). A word outside this set therefore cannot reach a consumer — it arrives
|
|
9583
9632
|
as the `gate` key being ABSENT, never as an unfamiliar word. Same rule for `Settlement.kind` and for
|
|
9584
9633
|
`GateOutcome.origin`.
|
|
9585
|
-
enum: [policy, hook, org, classifier, plan_mode, compliance, write_protection, ask_resolution]
|
|
9634
|
+
enum: [policy, hook, org, persisted_rule, classifier, plan_mode, compliance, write_protection, ask_resolution]
|
|
9586
9635
|
|
|
9587
9636
|
Settlement:
|
|
9588
9637
|
description: >
|
|
@@ -9751,7 +9800,7 @@ components:
|
|
|
9751
9800
|
# 服务对缺陷记录是整条不上帧 ⇒ 词表外的值在这条 wire 上到不了消费端。审批帧那一面不判成员,
|
|
9752
9801
|
# 所以 `AskOrigin` 本体保持真开(见该 schema 的长注)。这张 enum 是本 spec 里该词表的**唯一**
|
|
9753
9802
|
# 执法点;core 加词时改这一处。
|
|
9754
|
-
- enum: [content_question, unresolvable, org_unavailable, org_rule, hook, ask_rule, denial_limit_fallback, shell_gate_tighten, safety_tighten, policy]
|
|
9803
|
+
- enum: [content_question, unresolvable, org_unavailable, org_rule, rule_store_unavailable, hook, ask_rule, denial_limit_fallback, shell_gate_tighten, safety_tighten, policy]
|
|
9755
9804
|
description: >
|
|
9756
9805
|
WHO ASKED. Same-present/same-absent as `settlement` (I1). CLOSED here (and only here) — see the
|
|
9757
9806
|
enum note above.
|
|
@@ -10397,6 +10446,23 @@ components:
|
|
|
10397
10446
|
access: { type: string, enum: [read, create, edit] }
|
|
10398
10447
|
aliases: { type: array, items: { type: string } }
|
|
10399
10448
|
skillScopeEligible: { type: boolean, enum: [true] }
|
|
10449
|
+
base:
|
|
10450
|
+
type: string
|
|
10451
|
+
enum: [cwd, root]
|
|
10452
|
+
description: >
|
|
10453
|
+
core >= 7.9.1 (#635) — which base a RELATIVE path resolves against: the live cwd or the task root.
|
|
10454
|
+
Only present when declared; `base:"root"` is legal on read faces only (the engine refuses it elsewhere).
|
|
10455
|
+
absent:
|
|
10456
|
+
type: string
|
|
10457
|
+
enum: [none, base]
|
|
10458
|
+
description: >
|
|
10459
|
+
core >= 7.9.1 (#635) — what the tool targets when the param is ABSENT: nothing (`none`) or the base
|
|
10460
|
+
directory (`base`, read faces only — e.g. `Grep` with no path searches the cwd).
|
|
10461
|
+
patternParam:
|
|
10462
|
+
type: string
|
|
10463
|
+
description: >
|
|
10464
|
+
core >= 7.9.1 (#635) — the input key that carries a glob PATTERN (e.g. `Glob.pattern`); an absolute
|
|
10465
|
+
pattern there is the effective target. Must name a top-level input property.
|
|
10400
10466
|
McpToolRenderHints:
|
|
10401
10467
|
type: object
|
|
10402
10468
|
additionalProperties: false
|
|
@@ -11276,7 +11342,7 @@ components:
|
|
|
11276
11342
|
# 当天,一个**合法**的审批卡就会被严格消费端拒收。`x-open-enum` 只是意图标记,不解除 enum 的执法 ——
|
|
11277
11343
|
# 这正是本车刚从 `CheckpointGate` 拆掉的那个假开集,不在这里换个地方重犯。
|
|
11278
11344
|
# 闭集**执法**只属于**筛过的**那一面(`GateOutcome.origin`:引擎的 `screenGateOutcome` 判成员,
|
|
11279
|
-
# 出集即整条不上帧),所以那张 enum
|
|
11345
|
+
# 出集即整条不上帧),所以那张 enum 落在**那个引用点**,恰一处。已知十一词见下面的描述。
|
|
11280
11346
|
description: >
|
|
11281
11347
|
WHO raised an ask (`ToolApprovalFrame.origin`; server >= 7.57.0 / core 7.5.0, S-125③/#564) — core's
|
|
11282
11348
|
`ASK_ORIGINS`, ENGINE-STAMPED at the gate (core's words: "engine-stamped at the gate, never a policy's
|
|
@@ -11298,6 +11364,11 @@ components:
|
|
|
11298
11364
|
word could not. Both are classifier-eligible (arming auto mode is the deployment's explicit choice to
|
|
11299
11365
|
let the classifier resolve those classes).
|
|
11300
11366
|
|
|
11367
|
+
🔴 core 7.9.0 ADDS AN ELEVENTH WORD (server >= 7.67.0): `rule_store_unavailable` = the gate's own
|
|
11368
|
+
PERSISTED-RULE lane could not be READ for this call, so its deny/ask rows are unenforceable and the gate
|
|
11369
|
+
fails closed to a person. It is the personal-store sibling of `org_unavailable` (a governance source that
|
|
11370
|
+
cannot be read means ASK, never a silent allow).
|
|
11371
|
+
|
|
11301
11372
|
The SAME type is the `origin` member of `GateOutcome` on `tool_end` — one vocabulary, two faces.
|
|
11302
11373
|
|
|
11303
11374
|
RuleOffersAbsence:
|
|
@@ -13005,8 +13076,18 @@ components:
|
|
|
13005
13076
|
ServerWiringGates:
|
|
13006
13077
|
type: object
|
|
13007
13078
|
description: >
|
|
13008
|
-
The server's OWN assembly predicates (the half core's manifest does not cover)
|
|
13009
|
-
|
|
13079
|
+
The server's OWN assembly predicates (the half core's manifest does not cover) — server
|
|
13080
|
+
`routes/diagnostics.ts` `buildServerWiringGates`.
|
|
13081
|
+
|
|
13082
|
+
🔴 BREAKING (server >= 7.67.0 / S-178): the three POSTURE-FAMILY knobs are now `{value, source, note}`
|
|
13083
|
+
readings instead of bare values, and two of those rows are NEW. `streamApproval` is a GATE reading (a
|
|
13084
|
+
different axis: is this leg live) and `checkpointStore` is a presence bit — neither is a knob, so neither
|
|
13085
|
+
changed by one byte. Migration: `serverGates.durableApproval` -> `serverGates.durableApproval.value`.
|
|
13086
|
+
|
|
13087
|
+
⚠️ THIS SCHEMA DESCRIBES ONE GENERATION (same treatment as `TaskResult.terminal` in SDK 8.4.0): against a
|
|
13088
|
+
worker < 7.67.0 `durableApproval` is still a bare boolean on the wire and the other two keys are absent.
|
|
13089
|
+
The discriminator is the PEER'S VERSION, not the presence of these keys.
|
|
13090
|
+
required: [streamApproval, durableApproval, streamAskWindowMs, sessionAutoTitle, checkpointStore]
|
|
13010
13091
|
additionalProperties: false
|
|
13011
13092
|
properties:
|
|
13012
13093
|
streamApproval:
|
|
@@ -13016,7 +13097,39 @@ components:
|
|
|
13016
13097
|
same five-way predicate that gates `capabilities.streamApproval` and the decision endpoint's
|
|
13017
13098
|
501 — so the diagnostics page and the consumer-facing behavior cannot disagree.
|
|
13018
13099
|
enum: [active, no_tool_approval, protocol_disabled, no_backend, volatile_ask_ledger, no_park_facility]
|
|
13019
|
-
durableApproval:
|
|
13100
|
+
durableApproval:
|
|
13101
|
+
allOf:
|
|
13102
|
+
- { $ref: '#/components/schemas/PostureKnobReading' }
|
|
13103
|
+
- properties: { value: { type: boolean } }
|
|
13104
|
+
description: >
|
|
13105
|
+
`DURABLE_APPROVAL` (the durable-checkpoint gate's master switch) AND who set it. 🔴 On a single-user
|
|
13106
|
+
turnkey worker (REQUIRE_PRINCIPAL unset) the ABSENT default is now ON — conjoined with a durable store
|
|
13107
|
+
actually being present, so a `DB_BACKEND=memory` worker still mints nothing. A multi-tenant worker's
|
|
13108
|
+
absent default is unchanged (off). Pin it back with `DURABLE_APPROVAL=false` on the machine
|
|
13109
|
+
(`source: "env"` always wins).
|
|
13110
|
+
streamAskWindowMs:
|
|
13111
|
+
allOf:
|
|
13112
|
+
- { $ref: '#/components/schemas/PostureKnobReading' }
|
|
13113
|
+
# 🔴 `number`,不是 `integer`:server 的 `parseNumOrFail`(config.ts)只判 `Number.isFinite`,
|
|
13114
|
+
# 于是 `STREAM_ASK_WINDOW_MS=300000.5` 是一个**能启动**的部署,而这个值原样上诊断面 ——
|
|
13115
|
+
# 写 `integer` 会把一台合法 worker 的真实响应判违约。下界 0 是**真有**的拒启门(负窗拒启)。
|
|
13116
|
+
- properties: { value: { type: number, minimum: 0 } }
|
|
13117
|
+
description: >
|
|
13118
|
+
The approval window in milliseconds AND who set it. 🔴 On a single-user turnkey worker the absent
|
|
13119
|
+
default moved from 5 minutes to 24 HOURS (a person stepping away for ten minutes should not come back
|
|
13120
|
+
to a run that settled itself unattended); multi-tenant is unchanged at 300000. Pin it back with
|
|
13121
|
+
`STREAM_ASK_WINDOW_MS=300000`.
|
|
13122
|
+
⚠️ POSTURE ONLY FILLS AN EMPTY SEAT: where the derived 24h would collide with the existing
|
|
13123
|
+
cross-knob refuse-to-start inequality (`WINDOW + ADHOC_GRACE < ORPHAN_TTL`), posture YIELDS back to the
|
|
13124
|
+
engine default 300000 and reports `source: "engine-default"` rather than refusing to boot a deployment
|
|
13125
|
+
that changed nothing.
|
|
13126
|
+
sessionAutoTitle:
|
|
13127
|
+
allOf:
|
|
13128
|
+
- { $ref: '#/components/schemas/PostureKnobReading' }
|
|
13129
|
+
- properties: { value: { type: boolean } }
|
|
13130
|
+
description: >
|
|
13131
|
+
`SESSION_AUTO_TITLE` AND who set it. Its default is the SAME on every deployment shape (true), so this
|
|
13132
|
+
knob has NO posture arm — an unset one reads `source: "engine-default"` and says so in `note`.
|
|
13020
13133
|
checkpointStore: { type: boolean, description: 'A checkpoint store is wired (= the park facility exists).' }
|
|
13021
13134
|
|
|
13022
13135
|
WiringDiagnostics:
|
|
@@ -13689,12 +13802,32 @@ components:
|
|
|
13689
13802
|
kind: { type: string, enum: [project] }
|
|
13690
13803
|
root: { type: string, minLength: 1, description: 'The canonical directory this rule is scoped to. NEVER empty — an empty prefix contains EVERY cwd, which would silently promote a project rule to a global one.' }
|
|
13691
13804
|
|
|
13805
|
+
RuleBehavior:
|
|
13806
|
+
type: string
|
|
13807
|
+
description: >
|
|
13808
|
+
WHICH OF THE THREE a persisted rule is (core `RULE_BEHAVIORS`, closed; listed in PRECEDENCE order, so
|
|
13809
|
+
when rules of more than one behavior speak for one call the earliest member decides).
|
|
13810
|
+
|
|
13811
|
+
🔴 A RULE'S IDENTITY IS THE TRIPLE (behavior, text, scope) — core `sameRuleIdentity`; server >= 7.67.0 /
|
|
13812
|
+
core 7.9.0 #625. The same text under two behaviors is TWO DIFFERENT ROWS, which is why the revoke body
|
|
13813
|
+
requires this field and deliberately gives it NO default: a delete aimed at an `allow` that got defaulted
|
|
13814
|
+
onto the same-text `deny` removes a refusal the operator meant to keep, and answers 200.
|
|
13815
|
+
`allow` = the standing form of one recorded human approval ("don't ask again" on a card); `deny` / `ask` =
|
|
13816
|
+
the standing forms of "never run this" and "ask me every time", the same content-form rules the engine
|
|
13817
|
+
reads out of a settings file's deny/ask lists. ONE grammar, ONE canonical spelling and ONE matcher family
|
|
13818
|
+
serve all three — the behavior is a FIELD BESIDE the text, never part of it.
|
|
13819
|
+
enum: [deny, ask, allow]
|
|
13820
|
+
|
|
13692
13821
|
RuleCandidate:
|
|
13693
13822
|
type: object
|
|
13694
|
-
description:
|
|
13823
|
+
description: >
|
|
13824
|
+
One candidate rule: WHICH BEHAVIOR it is, the canonical text, and the scope it would land in (core
|
|
13825
|
+
`RuleCandidate`). `behavior` is new in server >= 7.67.0 / core 7.9.0 #625 — a card mints `allow`
|
|
13826
|
+
candidates only (a card is one person's yes), while the settings import now carries all three lists.
|
|
13695
13827
|
additionalProperties: false
|
|
13696
|
-
required: [rule, scope]
|
|
13828
|
+
required: [behavior, rule, scope]
|
|
13697
13829
|
properties:
|
|
13830
|
+
behavior: { $ref: '#/components/schemas/RuleBehavior' }
|
|
13698
13831
|
rule: { type: string, maxLength: 512 }
|
|
13699
13832
|
scope: { $ref: '#/components/schemas/RuleScope' }
|
|
13700
13833
|
|
|
@@ -13764,8 +13897,14 @@ components:
|
|
|
13764
13897
|
`uncovered` is a TWO-KEY RECORD, not a list: the two layers this version does not read are named in the
|
|
13765
13898
|
TYPE, so an empty list, a missing member or a duplicate is not expressible. A preview that reported only
|
|
13766
13899
|
the layers it read would be claiming a completeness it does not have.
|
|
13900
|
+
|
|
13901
|
+
🔴 server >= 7.67.0 / core 7.9.0 #625 — THE DENY AND ASK LISTS ARE IMPORTED TOO. Until then only the allow
|
|
13902
|
+
bucket was read and deny/ask entries were counted into an `uncovered.denyAskBuckets` seat that said "left
|
|
13903
|
+
in place"; now every candidate carries its own `behavior` and that seat is GONE — an entry that did not
|
|
13904
|
+
become a candidate is in `skipped` with its reason. A consumer rendering `uncovered.denyAskBuckets` reads
|
|
13905
|
+
`candidates[].behavior` instead.
|
|
13767
13906
|
additionalProperties: false
|
|
13768
|
-
required: [candidates, skipped, layers, uncovered]
|
|
13907
|
+
required: [candidates, skipped, translated, layers, uncovered]
|
|
13769
13908
|
properties:
|
|
13770
13909
|
candidates:
|
|
13771
13910
|
type: array
|
|
@@ -13775,6 +13914,25 @@ components:
|
|
|
13775
13914
|
type: array
|
|
13776
13915
|
items: { $ref: '#/components/schemas/CcImportSkippedRule' }
|
|
13777
13916
|
description: 'Entries that did not become candidates. `reason` is PROSE, not a code — see the schema.'
|
|
13917
|
+
translated:
|
|
13918
|
+
type: array
|
|
13919
|
+
description: >
|
|
13920
|
+
ALWAYS EMPTY in this version — a compatibility seat core keeps on the wire shape (core
|
|
13921
|
+
`ImportPreview.translated`, verbatim). It once carried entries whose MATCH FORM was rewritten on the
|
|
13922
|
+
way in (the other product's space-star suggestion form translated to this lane's colon-star). That
|
|
13923
|
+
translation is retired: space-star is now a first-class match form of this lane's own grammar, so an
|
|
13924
|
+
entry's match form imports as the file states it and nothing is ever pushed here. A reader rendering a
|
|
13925
|
+
"rewritten spellings" column from this seat renders an empty column, correctly.
|
|
13926
|
+
⚠️ Declared here from SDK 8.8.0 on: core has always emitted the key, so a closed schema without it
|
|
13927
|
+
judged every real 200 body a violation (a staleness fix, not a behavior change).
|
|
13928
|
+
items:
|
|
13929
|
+
type: object
|
|
13930
|
+
additionalProperties: false
|
|
13931
|
+
required: [from, to, scope]
|
|
13932
|
+
properties:
|
|
13933
|
+
from: { type: string }
|
|
13934
|
+
to: { type: string }
|
|
13935
|
+
scope: { $ref: '#/components/schemas/RuleScope' }
|
|
13778
13936
|
layers:
|
|
13779
13937
|
type: array
|
|
13780
13938
|
items: { $ref: '#/components/schemas/CcImportLayerReport' }
|
|
@@ -13814,9 +13972,12 @@ components:
|
|
|
13814
13972
|
indeterminate, release the claim and answer 503 `state.rule_import_retry` (server rules-consent.ts) —
|
|
13815
13973
|
so this schema honestly describes the two-value `status` only.
|
|
13816
13974
|
additionalProperties: false
|
|
13817
|
-
required: [candidateIndex, rule, scope, status, alreadyRedeemed, dot]
|
|
13975
|
+
required: [candidateIndex, behavior, rule, scope, status, alreadyRedeemed, dot]
|
|
13818
13976
|
properties:
|
|
13819
13977
|
candidateIndex: { type: integer, description: 'Index into the prepare preview''s candidate set (candidate space).' }
|
|
13978
|
+
behavior:
|
|
13979
|
+
allOf: [{ $ref: '#/components/schemas/RuleBehavior' }]
|
|
13980
|
+
description: 'server >= 7.67.0 / core 7.9.0 #625 — which of the three the landed row is (same value as the same-index candidate in the preview; one leg of the identity triple).'
|
|
13820
13981
|
rule: { type: string, description: 'Canonical rule text.' }
|
|
13821
13982
|
scope: { $ref: '#/components/schemas/RuleScope' }
|
|
13822
13983
|
status:
|
|
@@ -13898,27 +14059,71 @@ components:
|
|
|
13898
14059
|
PersistedRule:
|
|
13899
14060
|
type: object
|
|
13900
14061
|
description: >
|
|
13901
|
-
One LIVE persisted
|
|
14062
|
+
One LIVE persisted rule as `GET /v1/rules` puts it on the wire (server `PersistedRuleWireRow`).
|
|
13902
14063
|
Tombstones are already folded — every row here is live at `RuleListResult.rev`.
|
|
13903
14064
|
🔴 `scope` is the DISCRIMINANT STRING (`global` / `project:<root>`), NOT the `RuleScope` object the
|
|
13904
14065
|
import lane speaks: this is the exact byte sequence the revoke body wants back, so echo it VERBATIM
|
|
13905
14066
|
rather than re-serializing a parsed form (an equivalent-but-differently-spelled root matches nothing).
|
|
13906
|
-
|
|
14067
|
+
|
|
14068
|
+
🔴 THREE BEHAVIORS, NOT ALLOW-ONLY (server >= 7.67.0 / core 7.9.0 #625). Until 7.66.0 this schema said
|
|
14069
|
+
"the rule lane is ALLOW-only; deny/ask rules are the tightening direction and never appear here" — that
|
|
14070
|
+
sentence is now false, and `behavior` is the leg of the identity triple a revoke has to echo back.
|
|
13907
14071
|
additionalProperties: false
|
|
13908
|
-
required: [rule, scope, tool, match, command, adds]
|
|
14072
|
+
required: [behavior, rule, scope, tool, match, command, adds, source, status]
|
|
13909
14073
|
properties:
|
|
14074
|
+
behavior:
|
|
14075
|
+
allOf: [{ $ref: '#/components/schemas/RuleBehavior' }]
|
|
14076
|
+
description: 'Which of the three this row is. Part of the row''s IDENTITY — pass it back VERBATIM to revoke, or the delete aims at another behavior''s same-text row.'
|
|
13910
14077
|
rule: { type: string, description: 'Canonical rule text — `Bash(git status)` (exact) or `Bash(git status:*)` (prefix). Pass back VERBATIM to revoke.' }
|
|
13911
14078
|
scope: { type: string, description: 'Scope discriminant string: `global`, or `project:<root>` with a NON-EMPTY root. Pass back VERBATIM to revoke.' }
|
|
13912
|
-
tool:
|
|
14079
|
+
tool:
|
|
14080
|
+
type: string
|
|
14081
|
+
# 🔴 只钉非空,**不借**输入面那条 `maxLength: 190`(server 的 `LocalImportRowSchema` 帽的是**收进来的**
|
|
14082
|
+
# 行;列举面出去的行不过那道尺)。借一条别的面的约束来判这一面,迟早把一条合法行判成违约。
|
|
14083
|
+
minLength: 1
|
|
14084
|
+
description: >
|
|
14085
|
+
Which tool this row speaks for. 🔴 NOT A CLOSED SET from server >= 7.67.0 / core 7.9.0 #625 (the
|
|
14086
|
+
`enum: [Bash]` written here through SDK 8.7.0 is gone): the tool set is DERIVED from the engine
|
|
14087
|
+
catalogue's path-target declarations — `Bash` is the command grammar, any tool declaring a
|
|
14088
|
+
`pathTarget` (`Read` / `Write` / `Edit` / `Glob` / `Grep` / `NotebookEdit`, …) is the path grammar.
|
|
14089
|
+
The test is "does the engine's rule grammar speak for this name", and that roster lives in the
|
|
14090
|
+
engine's catalogue, not on this wire. READ IT; do not switch over a closed list. A name the grammar
|
|
14091
|
+
does not know is still a 400 on the input faces.
|
|
13913
14092
|
match:
|
|
13914
14093
|
type: string
|
|
13915
|
-
enum: [exact, prefix]
|
|
13916
|
-
description:
|
|
14094
|
+
enum: [exact, prefix, wildcard, subpath, path]
|
|
14095
|
+
description: >
|
|
14096
|
+
The match form (core `PersistedRuleMatch`, five members). `exact` = this one command only ·
|
|
14097
|
+
`prefix` = word-boundary prefix (the historical colon-star spelling, and the only spelling for a
|
|
14098
|
+
compound prefix) · `wildcard` = the space-star form, the SAME predicate as `prefix` on a single
|
|
14099
|
+
command body · `subpath` = the directory (read-containment) form, which never admits a command ·
|
|
14100
|
+
`path` = NEW in server >= 7.67.0, the path-family pattern grammar for deny/ask/allow rules (`//abs`,
|
|
14101
|
+
`~/`, root-relative, cwd-relative; `*` within a segment, `**` across segments).
|
|
14102
|
+
SDK 8.7.0 and earlier declared only the first two — a consumer rendering this cell off a closed list
|
|
14103
|
+
must add the other three.
|
|
13917
14104
|
command: { type: string, description: 'What the matcher actually compares against, parsed out of `rule` at mint time and stored so no consumer re-parses. Trust this + `match`, not your own parse of `rule`.' }
|
|
13918
14105
|
adds:
|
|
13919
14106
|
type: array
|
|
13920
14107
|
description: 'Every LIVE add of this rule (see RuleAdd — a real set, deliberately not folded).'
|
|
13921
14108
|
items: { $ref: '#/components/schemas/RuleAdd' }
|
|
14109
|
+
source:
|
|
14110
|
+
type: string
|
|
14111
|
+
enum: [user, project, session]
|
|
14112
|
+
description: >
|
|
14113
|
+
Which source this row came from (server >= 7.57.0 / core 7.5.0 design/389). DERIVED FROM `scope`
|
|
14114
|
+
(`global`<->`user`, `project`<->`project`, `session`<->`session`) — the row never carries a second
|
|
14115
|
+
source byte that could drift from its scope. With only the durable partition wired today the reachable
|
|
14116
|
+
values are `user | project`.
|
|
14117
|
+
⚠️ The IMPORT faces do NOT accept this key (nor `status`): POSTing a listing row straight back to
|
|
14118
|
+
local-import is a 400. Declared here from SDK 8.8.0 on — the server has emitted it since 7.57.0, so a
|
|
14119
|
+
closed schema without it judged every real listing row a violation.
|
|
14120
|
+
status:
|
|
14121
|
+
type: string
|
|
14122
|
+
enum: [live, shadowed-by-org]
|
|
14123
|
+
description: >
|
|
14124
|
+
The row's STANDING (server >= 7.57.0 / design/389): `live`, or `shadowed-by-org` when an org deny
|
|
14125
|
+
covers its command pattern. With no org partition wired today it is always `live` — branch on BOTH
|
|
14126
|
+
values now rather than optimising the constant away. Same staleness note as `source`.
|
|
13922
14127
|
|
|
13923
14128
|
RuleListResult:
|
|
13924
14129
|
type: object
|
|
@@ -13946,8 +14151,15 @@ components:
|
|
|
13946
14151
|
# 封闭:server 侧 zod 是 `.strict()` —— 把 `scope` 拼成 `scopes` 的客户端应当场知道,而不是
|
|
13947
14152
|
# 拿到一个「删掉了 global 那条」的意外结果。
|
|
13948
14153
|
additionalProperties: false
|
|
13949
|
-
required: [rule, scope]
|
|
14154
|
+
required: [behavior, rule, scope]
|
|
13950
14155
|
properties:
|
|
14156
|
+
behavior:
|
|
14157
|
+
allOf: [{ $ref: '#/components/schemas/RuleBehavior' }]
|
|
14158
|
+
description: >
|
|
14159
|
+
🔴 REQUIRED from server >= 7.67.0 (omit it and the body is a 400 `request.body_shape`) — WHICH
|
|
14160
|
+
BEHAVIOR's row to revoke, VERBATIM as the listing gave it. 🔴 DELIBERATELY NO DEFAULT: a revoke aimed
|
|
14161
|
+
at an `allow` that got defaulted onto the same-text `deny` deletes a refusal that was meant to stay,
|
|
14162
|
+
and hands the caller a 200. core's `sameRuleIdentity` names this exact failure.
|
|
13951
14163
|
rule: { type: string, minLength: 1, maxLength: 1024, description: 'The canonical rule text, VERBATIM as `RuleListResult.rules[].rule` gave it.' }
|
|
13952
14164
|
scope: { type: string, minLength: 1, maxLength: 4104, description: 'The scope discriminant string — `global` or `project:<root>` with a NON-EMPTY root (an empty root would match every cwd). VERBATIM as the listing gave it. Cap = "project:".length + server MAX_CWD_CHARS (8+4096) — the 1088 previously written here was the same stale independent copy the server itself fixed (rules.ts MAX_RULE_SCOPE_CHARS 顶注), found by the A-335 anchor sweep.' }
|
|
13953
14165
|
principal: { type: string, minLength: 1, maxLength: 190, description: 'OPERATOR-ONLY cross-tenant revoke. Absent (or your own principal) = revoke your own rule.' }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/sdk",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.8.0",
|
|
4
4
|
"description": "Typed, zero-runtime-dependency SDK for the Sema agent fleet usage plane. The shared substrate for all doors (CC/Codex MCP façade + web). Server-side only — tokens never enter the browser.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BUSL-1.1",
|