@sema-agent/sdk 18.0.0 → 18.2.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 +171 -0
- package/dist/errors.d.ts +22 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +23 -1
- package/dist/errors.js.map +1 -1
- package/dist/events.d.ts +8 -2
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js.map +1 -1
- package/dist/health.d.ts +40 -0
- package/dist/health.d.ts.map +1 -1
- package/dist/health.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/resources/admin.d.ts +3 -5
- package/dist/resources/admin.d.ts.map +1 -1
- package/dist/resources/admin.js.map +1 -1
- package/dist/resources/approvals.d.ts +6 -3
- package/dist/resources/approvals.d.ts.map +1 -1
- package/dist/resources/approvals.js +4 -2
- package/dist/resources/approvals.js.map +1 -1
- package/dist/resources/assistant.d.ts +5 -4
- package/dist/resources/assistant.d.ts.map +1 -1
- package/dist/resources/assistant.js +5 -4
- package/dist/resources/assistant.js.map +1 -1
- package/dist/resources/leader.d.ts +7 -1
- package/dist/resources/leader.d.ts.map +1 -1
- package/dist/resources/leader.js +7 -1
- package/dist/resources/leader.js.map +1 -1
- package/dist/resources/models.d.ts +5 -10
- package/dist/resources/models.d.ts.map +1 -1
- package/dist/resources/models.js +3 -1
- package/dist/resources/models.js.map +1 -1
- package/dist/resources/tasks.d.ts +9 -2
- package/dist/resources/tasks.d.ts.map +1 -1
- package/dist/resources/tasks.js +9 -2
- package/dist/resources/tasks.js.map +1 -1
- package/dist/settings.d.ts +6 -2
- package/dist/settings.d.ts.map +1 -1
- package/dist/types.d.ts +119 -27
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/openapi.yaml +256 -56
- package/package.json +2 -2
package/openapi.yaml
CHANGED
|
@@ -2416,7 +2416,23 @@ paths:
|
|
|
2416
2416
|
required: [rules]
|
|
2417
2417
|
properties:
|
|
2418
2418
|
rules: { $ref: '#/components/schemas/StoredSessionRules' }
|
|
2419
|
-
'400':
|
|
2419
|
+
'400':
|
|
2420
|
+
description: >-
|
|
2421
|
+
400 — the rules body is refused BEFORE anything is written (not one byte reaches the store). Branch on `errorCode`, never on the sentence.
|
|
2422
|
+
`rules.legacy_tool_name` (server >= 7.105.0; the `rules.*` family, the SDK lands it on `BadRequestError`): a tool-name bucket (`toolAllow` / `toolDeny`) entry
|
|
2423
|
+
that would be written but could never run — an engine-retired name, a `__` name without a protocol prefix, or a protocol name whose peer segment the
|
|
2424
|
+
engine cannot mint. Body keys (top level; the SDK reads them from `err.extra`): `field` (which bucket), `name` (which entry), `verdict`
|
|
2425
|
+
(`retired` / `unprefixed_namespace`, server >= 7.116.0; `unmintable_segment`, server >= 7.118.0), `currentName` (server >= 7.116.0; present when
|
|
2426
|
+
there is a 1:1 successor), `guidance` (server >= 7.119.0; the engine judge's wording of the fix, byte for byte — carried by `retired` and
|
|
2427
|
+
`unmintable_segment`, absent for `unprefixed_namespace`). 🔴 server >= 7.123.0 also lands a protocol name with an EMPTY TOOL SEGMENT
|
|
2428
|
+
(`mcp__<server>__`, `a2a__<peer>__`) here, as `verdict: "unmintable_segment"`; server 7.116.0–7.122.x answered `400 request.field_invalid`
|
|
2429
|
+
for it — a caller that branched on that code for this shape now branches on `rules.legacy_tool_name` (the body's `verdict` tells the shapes apart).
|
|
2430
|
+
`request.field_invalid`: a bucket that is not a list of non-empty strings (a bare string, `null`, a non-string member) and — behavior change
|
|
2431
|
+
in server >= 7.123.0 — an EMPTY or BLANK (whitespace-only) member, which earlier servers took in (200); the sentence is the engine's own,
|
|
2432
|
+
match on the code. Also `request.id_invalid` (malformed session id) and a malformed body.
|
|
2433
|
+
content:
|
|
2434
|
+
application/json:
|
|
2435
|
+
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
2420
2436
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
2421
2437
|
'403':
|
|
2422
2438
|
description: 403 `loosen_forbidden` — a non-operator write tried to relax the rules (tighten-only).
|
|
@@ -3116,7 +3132,20 @@ paths:
|
|
|
3116
3132
|
content:
|
|
3117
3133
|
application/json:
|
|
3118
3134
|
schema: { $ref: '#/components/schemas/ImportStaged' }
|
|
3119
|
-
'400':
|
|
3135
|
+
'400':
|
|
3136
|
+
description: >-
|
|
3137
|
+
400 — malformed input (the `policy` face is judged by the same write-door reader as `PUT /v1/sessions/{sessionId}/policy`, BEFORE any staging
|
|
3138
|
+
is created, so a refused push leaves nothing behind). Branch on `errorCode`, never on the sentence. `rules.legacy_tool_name` (server >= 7.105.0):
|
|
3139
|
+
a record's tool-name bucket (`toolAllow` / `toolDeny`) holds a name that could never run — an engine-retired name, a `__` name without a protocol prefix,
|
|
3140
|
+
or a protocol name whose peer segment the engine cannot mint. Body keys (top level; the SDK reads them from `err.extra`): `field`, `name`, `verdict`
|
|
3141
|
+
(`retired` / `unprefixed_namespace`, server >= 7.116.0; `unmintable_segment`, server >= 7.118.0), `currentName` (server >= 7.116.0, when there is a 1:1 successor),
|
|
3142
|
+
`guidance` (server >= 7.119.0, the engine judge's wording; absent for `unprefixed_namespace`). 🔴 server >= 7.123.0 also lands a protocol name with an EMPTY TOOL
|
|
3143
|
+
SEGMENT (`mcp__<server>__`, `a2a__<peer>__`) here (`verdict: "unmintable_segment"`); server 7.116.0–7.122.x answered `400 request.field_invalid` for it.
|
|
3144
|
+
`request.field_invalid`: a bucket that is not a list of non-empty strings and — behavior change in server >= 7.123.0 — an EMPTY or BLANK member, which earlier
|
|
3145
|
+
servers took in (the sentence carries the `policy: [i].rules: ` position prefix and then the engine's own sentence; match on the code).
|
|
3146
|
+
content:
|
|
3147
|
+
application/json:
|
|
3148
|
+
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
3120
3149
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
3121
3150
|
'404': { $ref: '#/components/responses/NotFound' }
|
|
3122
3151
|
'409':
|
|
@@ -3234,7 +3263,9 @@ paths:
|
|
|
3234
3263
|
Frames: `meta` ({type,version,mode:"approvals-delta",pollMs}), then `synced` ({type,count}) once the
|
|
3235
3264
|
first full snapshot has been emitted, then `pending`/`resolved` deltas; plus `heartbeat` ({type}) on the
|
|
3236
3265
|
keep-alive tick and a terminal `error` ({type,errorCode:"STREAM_MAX_DURATION",…}) when the 15-min cap
|
|
3237
|
-
fires.
|
|
3266
|
+
fires — or, server >= 7.122.0, `error` with `errorCode:"draining"` at the moment the instance enters drain (same code and
|
|
3267
|
+
sentence as the billable-submit 503 `draining`; the server closes the stream right after the frame, reconnect to the
|
|
3268
|
+
replacement instance). (Corrected 2026-07-31: this list used to name only meta/pending/resolved — a consumer written to
|
|
3238
3269
|
it silently drops three frame kinds it really receives.) Each data payload mirrors its SSE event name in
|
|
3239
3270
|
`data.type` — proxy-safe dispatch. Cross-replica by
|
|
3240
3271
|
construction (polls the SHARED checkpoint table). 15-min cap + heartbeats; a DB blip retries, never
|
|
@@ -3735,8 +3766,12 @@ paths:
|
|
|
3735
3766
|
`ErrorResponse`-shaped. Codes: "request.body_shape" (bad/missing `decision`, OR an unrecognised
|
|
3736
3767
|
top-level key — server >= 7.86.0 / S-438 key closure, the body carries `unknownKeys` /
|
|
3737
3768
|
`unsupportedKeys`) · "request.field_conflict" (`edit` without a non-empty `editedPlan`;
|
|
3738
|
-
`editedPlan` present on approve/reject; `permissionModeAfter` sent with `
|
|
3739
|
-
`permissionModeAfter` on a task
|
|
3769
|
+
`editedPlan` present on approve/reject; `permissionModeAfter` sent with `reject`;
|
|
3770
|
+
`permissionModeAfter` on a task whose stored permission mode is not `plan`) — match these two by CODE;
|
|
3771
|
+
server >= 7.122.0: `approve` and `edit` both carry the plan out of plan mode and both take the key, and a
|
|
3772
|
+
run's mode word has ONE source, the stored submit body (an operator `AUTONOMY=plan` task is stored as `plan`
|
|
3773
|
+
and takes the key); <= 7.121.x only `approve` took it and the second conflict read "not submitted with
|
|
3774
|
+
`permissionMode:"plan"`" ·
|
|
3740
3775
|
"request.field_invalid" (non-string `reason`; `permissionModeAfter` outside the two-word closed
|
|
3741
3776
|
set — zero widening arm) · "request.path_malformed" (a bad percent-encoded path segment —
|
|
3742
3777
|
server >= 7.86.0 / S-430 turned that family from 500 `internal.error` into a 400 across 16 doors).
|
|
@@ -4117,8 +4152,9 @@ paths:
|
|
|
4117
4152
|
description: >
|
|
4118
4153
|
READ-ONLY catalog of `@mention`-pickable models. The user selects a model PER-TASK by typing `@<name>` in
|
|
4119
4154
|
the objective body (the service allowlist-parses it; the client never re-decides). Envelope
|
|
4120
|
-
`{ models, default, defaultModel }` (`default` = the deployment default model id,
|
|
4121
|
-
internal `default` alias is hidden; `defaultModel` = the same default as `{id, name?}` in one piece
|
|
4155
|
+
`{ models, default, defaultModel, droppedEntries? }` — see `ModelsResponse` (`default` = the deployment default model id,
|
|
4156
|
+
display-only — the internal `default` alias is hidden; `defaultModel` = the same default as `{id, name?}` in one piece;
|
|
4157
|
+
`droppedEntries` = server >= 7.123.0, the catalog entries the read leg dropped, in the same generation as `models`).
|
|
4122
4158
|
🔴 NON-SECRET: only name/id/provider/reasoning/vision + the E4/E7 capability fields — NEVER baseUrl/apiKey/
|
|
4123
4159
|
headers (the service strips them). Fail-safe: on error, render an empty picker (never block).
|
|
4124
4160
|
responses:
|
|
@@ -4126,26 +4162,7 @@ paths:
|
|
|
4126
4162
|
description: Model catalog (possibly empty).
|
|
4127
4163
|
content:
|
|
4128
4164
|
application/json:
|
|
4129
|
-
schema:
|
|
4130
|
-
type: object
|
|
4131
|
-
# 🔴 封闭 + `defaultModel` 补登记(census 批2 第三段,2026-07-30):铸造点
|
|
4132
|
-
# `routes/capabilities.ts` 三键字面量。`defaultModel`([865]③ id/name 撕裂消解,server
|
|
4133
|
-
# 已发多版)SDK `models.list()` 的返回类型早就带,**spec 是唯一没登记的一侧** —— 生成式
|
|
4134
|
-
# 消费方对它全瞎。`name` 条件(目录无命中即省略),`id` 恒在。
|
|
4135
|
-
additionalProperties: false
|
|
4136
|
-
required: [models, default, defaultModel]
|
|
4137
|
-
properties:
|
|
4138
|
-
models:
|
|
4139
|
-
type: array
|
|
4140
|
-
items: { $ref: '#/components/schemas/ModelInfo' }
|
|
4141
|
-
default: { type: string, description: "deployment default model id (display-only; legacy id-form, byte-stable)" }
|
|
4142
|
-
defaultModel:
|
|
4143
|
-
type: object
|
|
4144
|
-
additionalProperties: false
|
|
4145
|
-
required: [id]
|
|
4146
|
-
properties:
|
|
4147
|
-
id: { type: string }
|
|
4148
|
-
name: { type: string, description: 'the catalog @handle of the default model; omitted when the catalog has no match (env single-model lane).' }
|
|
4165
|
+
schema: { $ref: '#/components/schemas/ModelsResponse' }
|
|
4149
4166
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
4150
4167
|
|
|
4151
4168
|
/v1/elicitations/{id}/respond:
|
|
@@ -4668,7 +4685,8 @@ paths:
|
|
|
4668
4685
|
(`LEADER_ENABLED` off) the answer depends on the server: server >= 7.116.0 mounts the route unconditionally and answers
|
|
4669
4686
|
**501 `capability.leader_endpoint_required`** (new code; under multi-tenant the identity gate's 401 still comes first);
|
|
4670
4687
|
<= 7.115.x did not register the route at all → the generic **404** `not_found.route`. Detect "leader unavailable" by
|
|
4671
|
-
`errorCode` (or the `capabilities.leader` bit
|
|
4688
|
+
`errorCode` (or the `capabilities.leader` bit — server >= 7.122.0 also reads false on a deployment whose operator runs `AUTONOMY=plan`, where a submit answers
|
|
4689
|
+
422 `request.autonomy_lane_refused` instead; see `Capabilities.leader`), not by the status alone.
|
|
4672
4690
|
|
|
4673
4691
|
|
|
4674
4692
|
🔴 IDEMPOTENCY (server >= 7.24.0): this POST now consumes the `Idempotency-Key` header — the header is
|
|
@@ -4717,6 +4735,20 @@ paths:
|
|
|
4717
4735
|
content:
|
|
4718
4736
|
application/json:
|
|
4719
4737
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
4738
|
+
'422':
|
|
4739
|
+
description: >-
|
|
4740
|
+
errorCode "request.autonomy_lane_refused" (server >= 7.122.0) — the deployment runs the operator `AUTONOMY=plan`: every task starts
|
|
4741
|
+
in plan mode and leaves it only when a person approves its plan through plan review, and a leader task's workers have no plan
|
|
4742
|
+
review channel, so they could neither write nor hand their plan to anyone who can approve it. REFUSED at the door, NO run created;
|
|
4743
|
+
a replay with the same `Idempotency-Key` gets the same 422 (the idempotency key is not consumed). The `capabilities.leader` bit
|
|
4744
|
+
reads false on such a deployment (the same judgement as this refusal) — read it, or `GET /v1/policy` `autonomy`, beforehand. Exits: submit the work as a run (`POST /v1/runs`, plan reviewed through
|
|
4745
|
+
`POST /v1/assistant/tasks/{taskId}/plan_review`), or ask the operator to set `AUTONOMY=read-only` or `ask` (leader tasks run
|
|
4746
|
+
there). Not the hosted-posture refusal (`request.host_posture_refused`): that one is the tenant axis, this one is the AUTONOMY
|
|
4747
|
+
axis. A change to `plan` after acceptance is caught where the run is born: the 202'd run ends with the same sentence in
|
|
4748
|
+
`GET /v1/leader/{leaderRunId}` `error` and no worker is started.
|
|
4749
|
+
content:
|
|
4750
|
+
application/json:
|
|
4751
|
+
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
4720
4752
|
'409':
|
|
4721
4753
|
description: >-
|
|
4722
4754
|
errorCode "conflict.leader_run_exists" (server >= 7.24.0) — your `Idempotency-Key` hit a leader run
|
|
@@ -7206,7 +7238,12 @@ components:
|
|
|
7206
7238
|
`config.permission_mode_unavailable`. `bypassPermissions` RELEASES the ten releasable ask classes (server >= 7.115.0: the tenth is `unstated`, a server-tool call nobody stated)
|
|
7207
7239
|
and DISCLOSES each (`tool_end.gate.disposition.released` + one `engine_notice` `permission.ask_released_by_mode` per (mode, class) per run);
|
|
7208
7240
|
immune classes (deployment-authored, ask / org rules, hooks, ancestors, questions …) still ask; a write whose protection
|
|
7209
|
-
cannot be judged is refused (`deniedBy: mode`)
|
|
7241
|
+
cannot be judged is refused (`deniedBy: mode`) on the file tools — and, from server >= 7.122.0 / core 7.47.0, RELEASED on the SHELL face
|
|
7242
|
+
(an eleventh class, `write_protection_unresolved`, for a caller-supplied tool whose wire name is exactly `Bash` or `Monitor` and which
|
|
7243
|
+
declares a write-path target; see `ModeRelease.reason`). `plan` (server >= 7.122.0): the engine's plan mode and nothing the service adds —
|
|
7244
|
+
the tool table equals `default`'s, the engine mounts the plan-presenting tool, and a write or any non-read-only call is asked AT CALL TIME by the
|
|
7245
|
+
engine's plan gate (a card where somebody can answer, a refusal where nobody can; a delegated sub-agent inherits plan as its ceiling); up to
|
|
7246
|
+
7.121.x the service also mapped `plan` to read-only hands, withheld the delegation tool and refused `Workflow`. Request vocabulary: SIX words (server >= 7.119.0) — `dontAsk`, the engine's
|
|
7210
7247
|
"auto-refuse" mode, is accepted and passes through verbatim: the ENGINE refuses the calls that would ask (no card, no parked row,
|
|
7211
7248
|
`tool_end.gate.disposition = { kind: denied, deniedBy: mode, mode: dontAsk, … }`), the run ends normally, and it is never looser
|
|
7212
7249
|
than `default`. One exception: a PreToolUse hook's OWN ask, when no other class in that ask's set backs it, is still handed to a person
|
|
@@ -7216,7 +7253,7 @@ components:
|
|
|
7216
7253
|
hold for <= 7.105.0 only.
|
|
7217
7254
|
CC-parity permission-mode INTENT — the values THIS wire's closed submit-gate accepts (the first five on server <= 7.118.x,
|
|
7218
7255
|
plus `dontAsk` from 7.119.0 = the engine's whole mode vocabulary, `capabilities.permissionModes`). The frontend (TUI shell / web portal) carries the RAW mode; the SERVICE interprets it TIGHTEN-ONLY vs the deployment baseline:
|
|
7219
|
-
`plan` ⇒ mount present_plan (core enablePlanMode) + read-only hands (CC EnterPlanMode research);
|
|
7256
|
+
`plan` ⇒ mount present_plan (core enablePlanMode) + read-only hands (CC EnterPlanMode research) — that is the <= 7.121.x reading; server >= 7.122.0: see the `plan` sentence in the first block;
|
|
7220
7257
|
`default` adds the manual ask gate on non-exempt writes (scratchpad dirs / remembered session
|
|
7221
7258
|
exemptions still auto-allow — not literally every Write/Edit); the server emits the SAME gate-policy
|
|
7222
7259
|
for `auto` as for `default` — sending `auto` is NOT itself what arms core's auto-mode classifier; that
|
|
@@ -7443,6 +7480,10 @@ components:
|
|
|
7443
7480
|
`MANUAL_MODE_SHELL_GATE=always`, write protection, governance, a hook's ask and plan-mode asks still ask (a matching `request` member then shows as `allowRuleShadowed` on the
|
|
7444
7481
|
card). The submit gate judges only the shape (array of strings, at most 1000 entries => 400) and the NAMES (the same judge and the same sentence as `deny` / `ask`: a retired name,
|
|
7445
7482
|
an unprefixed short name, or a protocol name whose server segment cannot be minted / is missing / is a wildcard (`mcp__*`) is a whole-request 422) — never the content.
|
|
7483
|
+
🔴 server >= 7.118.0: the NAME layer of the allow side moved to the engine — a retired name, an unprefixed short name or an unmintable protocol name is ACCEPTED here (no 422) and the run opens with an
|
|
7484
|
+
`engine_notice` `permission.allowed_tool_not_granted` (`entries[].reason: tool_name`); the `deny` / `ask` buckets still refuse that family with a whole-request 422. 🔴 server >= 7.123.0 (core 7.48.0) also accepts a
|
|
7485
|
+
protocol name with an EMPTY TOOL SEGMENT (`mcp__<server>__`, `a2a__<peer>__`) in this bucket (server 7.118.0–7.122.x refused it on every table). One name, three outcomes:
|
|
7486
|
+
allow side accepts + notice, deny / ask side refuses, session-rule write doors answer `400 rules.legacy_tool_name` (`verdict: unmintable_segment`).
|
|
7446
7487
|
🔴 THE 422 SENTENCE (server >= 7.117.0): `error` starts with `request settings cannot be applied as written: ` (<= 7.116.x: a different sentence that said tighten-only — all three
|
|
7447
7488
|
buckets share this exit, and the old head misled a caller writing a tightening rule and lied about the allow bucket). Do NOT dispatch on the sentence: it carries no code of its own, so
|
|
7448
7489
|
`errorCode` is the status-derived coarse code `request.unprocessable`.
|
|
@@ -9077,7 +9118,16 @@ components:
|
|
|
9077
9118
|
asyncRuns: { type: boolean }
|
|
9078
9119
|
artifacts: { type: boolean }
|
|
9079
9120
|
approvals: { type: boolean }
|
|
9080
|
-
leader:
|
|
9121
|
+
leader:
|
|
9122
|
+
type: boolean
|
|
9123
|
+
description: >-
|
|
9124
|
+
The `POST /v1/leader` lane. server >= 7.122.0 reads the conjunction of two facts: the leader face is mounted (`LEADER_ENABLED` etc.) AND the
|
|
9125
|
+
operator entry floor takes leader submissions — the same judgement as the 422 `request.autonomy_lane_refused` at the door (a leader task's
|
|
9126
|
+
workers have no plan review channel). So on a deployment whose operator runs `AUTONOMY=plan` the bit reads false and a direct submit still
|
|
9127
|
+
answers 422 `request.autonomy_lane_refused`; with `AUTONOMY=read-only` / `ask` / unset the bit follows the face. A false bit from an absent face
|
|
9128
|
+
answers 501 `capability.leader_endpoint_required` on submit (404 `not_found.route` on <= 7.115.x) — tell the two falses apart by the submit's
|
|
9129
|
+
`errorCode`, or read `GET /v1/policy` `autonomy` beforehand. <= 7.121.x (historical reading): the bit read the face only — true on a `plan`
|
|
9130
|
+
deployment, no prediction of the refusal.
|
|
9081
9131
|
version: { type: string }
|
|
9082
9132
|
scenarios:
|
|
9083
9133
|
type: array
|
|
@@ -9566,6 +9616,9 @@ components:
|
|
|
9566
9616
|
`engine_notice` `permission.allowed_tool_not_granted`; any layer's deny / ask rule, operator `APPROVAL_REQUIRE` / `APPROVAL_NEVER_AUTO` / shell floor / write protection /
|
|
9567
9617
|
governance, a hook's ask and plan-mode asks still ask (a matching member then shows as `allowRuleShadowed` on the card). The submit gate judges only the shape and the NAMES (retired
|
|
9568
9618
|
name / unprefixed short name / unmintable protocol server segment => 422, at most 1000 entries => 400) — never the content.
|
|
9619
|
+
🔴 server >= 7.118.0: the allow side's NAME layer moved to the engine (retired / short / unmintable names are accepted there and announced with `engine_notice` `permission.allowed_tool_not_granted`; `deny` / `ask` still 422);
|
|
9620
|
+
server >= 7.123.0 also accepts a protocol name with an EMPTY TOOL SEGMENT (`mcp__<server>__`) on the allow side (server 7.118.0–7.122.x refused it on every table):
|
|
9621
|
+
allow side accepts + notice, deny / ask side refuses, session-rule write doors answer `400 rules.legacy_tool_name`.
|
|
9569
9622
|
🔴 ABSENT `allowLayer` with `allowGrant` present = a 7.115.0–7.116.x server: allow is a STATEMENT (it does not clear the engine's own write gate / shell checks; a content form
|
|
9570
9623
|
is a whole-request 422). ABSENT KEY altogether (no `settings`) = an older server (<= 7.114.x), which read `allow` as a WHITELIST (everything off the list refused) — do not put
|
|
9571
9624
|
anything in the allow bucket there. NOT the same bit as `taskSettings.permissions` (unchanged, still a boolean: "this server accepts the `settings.permissions` face"). The
|
|
@@ -9744,10 +9797,11 @@ components:
|
|
|
9744
9797
|
does not know auto" and "it knows auto but this box has no entitlement source" would collapse to
|
|
9745
9798
|
the same false, and a shell must do different things for those. `reason` is present ONLY when
|
|
9746
9799
|
`armed` is false; read its vocabulary as an OPEN set (server already grew it from four words to
|
|
9747
|
-
six). `model` is omitted when the classifier route cannot be resolved (the server logs the
|
|
9800
|
+
six, and to seven with `operator_floor` in server >= 7.123.0). `model` is omitted when the classifier route cannot be resolved (the server logs the
|
|
9748
9801
|
engine's refusal rather than 500-ing the read face). `?permissionMode=<mode word>` folds the
|
|
9749
9802
|
caller's INTENT into the verdict (server >= 7.119.0 takes the six words of `capabilities.permissionModes` — `dontAsk` answers
|
|
9750
|
-
`armed: false` / `reason: mode_not_auto
|
|
9803
|
+
`armed: false` / `reason: mode_not_auto`, except on a deployment whose operator entry floor rewrites the word — `AUTONOMY=plan`, where
|
|
9804
|
+
server >= 7.123.0 answers `operator_floor`, see `reason`; server <= 7.118.x takes five); anything outside the server's words is a 400
|
|
9751
9805
|
`request.field_invalid`.
|
|
9752
9806
|
# 🔴 required 只有**三位**:武装两键(armed / reason)是 server >= 7.57.0 (S-80)
|
|
9753
9807
|
# 才有的,而本包的支持地板是 3.0.0 => every 7.x <= 7.56.0 server is inside the promised face and
|
|
@@ -9768,7 +9822,17 @@ components:
|
|
|
9768
9822
|
fold that absence into false (it would render a 7.50 box that IS arming as "auto == default").
|
|
9769
9823
|
reason:
|
|
9770
9824
|
type: string
|
|
9771
|
-
enum: [mode_not_auto, deployment_incapable, org_denied, local_denied, settings_denied, resolver_fault]
|
|
9825
|
+
enum: [mode_not_auto, operator_floor, deployment_incapable, org_denied, local_denied, settings_denied, resolver_fault]
|
|
9826
|
+
description: >
|
|
9827
|
+
Why `armed` is false — the server's closed SEVEN words, in judgement order (read as an open set; keep a default arm).
|
|
9828
|
+
`mode_not_auto` = this request's intent (the `?permissionMode=` query word) is not `auto` and that word reaches the engine as it is.
|
|
9829
|
+
`operator_floor` (server >= 7.123.0) = this deployment's operator entry floor (`AUTONOMY=plan`) rewrote the intent into another word, and that
|
|
9830
|
+
word is not `auto`: the word that reaches the engine is the operator's, so the way out is the operator changing the level, NOT the word the
|
|
9831
|
+
request sends. On an `AUTONOMY=plan` deployment an absent intent (answered as the `auto` intent), `auto` and any word looser than `plan` read
|
|
9832
|
+
`operator_floor`; an intent that IS `plan` stays `mode_not_auto` (the word arrives as sent, not rewritten by the floor).
|
|
9833
|
+
Server <= 7.122.x answers `mode_not_auto` for both cases. The rest: `deployment_incapable` = no classifier seat mounted;
|
|
9834
|
+
`org_denied` = this principal's caps say auto is off and no local deny is set (the center's explicit deny, or its fail-closed refusal); `local_denied` = the local `PERMISSIONS_DISABLE_AUTO_MODE`;
|
|
9835
|
+
`settings_denied` = the settings layer folds auto (run-level, not produced by this read face); `resolver_fault` = the resolver threw.
|
|
9772
9836
|
model: { type: string }
|
|
9773
9837
|
readFace:
|
|
9774
9838
|
type: ["string", "null"]
|
|
@@ -9928,13 +9992,16 @@ components:
|
|
|
9928
9992
|
taskWriteFaceOpen:
|
|
9929
9993
|
type: boolean
|
|
9930
9994
|
description: >
|
|
9931
|
-
server >= 7.95.0 (S-591; value meaning refined at 7.96.0 / S-613; mint `routes/capabilities.ts
|
|
9932
|
-
`taskWriteFaceRefusal(deps.config) === undefined &&
|
|
9995
|
+
server >= 7.95.0 (S-591; value meaning refined at 7.96.0 / S-613; mint `routes/capabilities.ts` =
|
|
9996
|
+
`taskWriteFaceRefusal(deps.config) === undefined && autonomyKeepsOpenWriteFace(deps.config.autonomy)` from server >= 7.122.0;
|
|
9997
|
+
up to 7.121.x the right half was `autonomyOverrides(deps.config.autonomy).writeFace !== "roots"`)
|
|
9933
9998
|
— DISCLOSURE BIT OF THE WRITE-CONTAINMENT FACE: does this deployment honour the task-level "open the write
|
|
9934
9999
|
fence" declaration (`permissionMode:"bypassPermissions"` ⇒ `TaskSpec.writeFace:"open"`, writes outside the
|
|
9935
10000
|
workspace roots)? `false` has two forms: (1) the hosted-posture gate refuses ⇒ sending that mode gets
|
|
9936
|
-
`422 request.host_posture_refused`; (2) the deployment runs `AUTONOMY=read-only
|
|
9937
|
-
accepted but the write face is clamped back to roots — the declaration silently does nothing.
|
|
10001
|
+
`422 request.host_posture_refused`; (2) the deployment runs `AUTONOMY=read-only` ⇒ the request is
|
|
10002
|
+
accepted but the write face is clamped back to roots — the declaration silently does nothing; server >= 7.122.0: `AUTONOMY=plan`
|
|
10003
|
+
reads `false` too, but because the entry mode word is clamped to `plan` at admission (the engine's plan mode runs instead of
|
|
10004
|
+
`bypassPermissions`; up to 7.121.x it was the same read-only-hands + roots clamp as `AUTONOMY=read-only`, and a hosted deployment answered 422 `request.host_posture_refused` where it now accepts the request into plan). Three states
|
|
9938
10005
|
are folded into one bit on purpose: the caller has exactly one decision (send that key or not); tier and
|
|
9939
10006
|
evidence live in the refusal body and the operator's `GET /v1/diagnostics/wiring`. It speaks ONLY for the
|
|
9940
10007
|
write-containment cell — the other two columns of `bypassPermissions` are unaffected.
|
|
@@ -10190,6 +10257,9 @@ components:
|
|
|
10190
10257
|
segment cannot be minted / is missing / is a wildcard (`mcp__*`) is a 400 too, and from 7.117.0 so is a retired name / unprefixed short
|
|
10191
10258
|
name (the name layer is judged by the same judge as the allow bucket) and a list of more than 1000 entries (top-level `skills[]` and
|
|
10192
10259
|
`agents[].skills[]` judge identically). Probe `capabilities.skillToolLists`.
|
|
10260
|
+
🔴 The name-layer 400s above hold for server 7.116.x–7.117.x only. server >= 7.118.0: the allow side's name layer moved to the engine — a retired name / unprefixed short name / unmintable protocol name is ACCEPTED here and the run opens with an
|
|
10261
|
+
`engine_notice` `permission.allowed_tool_not_granted` (`entries[].reason: tool_name`); server >= 7.123.0 also accepts a protocol name with an EMPTY TOOL SEGMENT (`mcp__<server>__`, `a2a__<peer>__`) here (server 7.118.0–7.122.x refused it).
|
|
10262
|
+
One name, three outcomes: allow side accepts + notice, deny / ask side refuses, session-rule write doors answer `400 rules.legacy_tool_name` (`disallowedTools` below is a deny side).
|
|
10193
10263
|
disallowedTools:
|
|
10194
10264
|
type: array
|
|
10195
10265
|
items: { type: string }
|
|
@@ -10204,6 +10274,8 @@ components:
|
|
|
10204
10274
|
user audience, on the session stream). 🔴 The resume legs judge the stored body the same way: a parked task whose stored skill `disallowedTools` carries such an entry answers
|
|
10205
10275
|
409 `resume_blocked_by_policy` (`blockedBy: "request.field_invalid"`, same sentence) BEFORE the claim — row and card untouched; a terminal run's `POST /v1/runs/{taskId}/steer`
|
|
10206
10276
|
answers it before minting the wake card. Why: engine 7.41 trimmed whitespace (`"Bash "` was a working deny), engine 7.42 reads verbatim (reads as nothing). The allow side does not refuse.
|
|
10277
|
+
🔴 A protocol name with an EMPTY TOOL SEGMENT (`mcp__<server>__`, `a2a__<peer>__`) is refused here (server >= 7.123.0: `error` is the engine's entry-reading sentence, `... reads as nothing (tool_name) ...`), while `allowedTools` accepts it from 7.123.0 —
|
|
10278
|
+
one name, three outcomes: allow side accepts + notice, deny / ask side refuses, session-rule write doors answer `400 rules.legacy_tool_name`.
|
|
10207
10279
|
|
|
10208
10280
|
McpServerSpec:
|
|
10209
10281
|
type: object
|
|
@@ -10937,6 +11009,92 @@ components:
|
|
|
10937
11009
|
`"other"`). This is the "where did those 180 404s actually land" cell. Empty object = zero failures;
|
|
10938
11010
|
key absent = an older server.
|
|
10939
11011
|
|
|
11012
|
+
ModelsResponse:
|
|
11013
|
+
type: object
|
|
11014
|
+
description: >
|
|
11015
|
+
The `GET /v1/models` 200 body (the envelope; service `src/http/routes/capabilities.ts` mints the keys as literals).
|
|
11016
|
+
`models` = the `@mention`-pickable catalog (`ModelInfo`); `default` = the deployment default model id (display-only, legacy id
|
|
11017
|
+
form, byte-stable); `defaultModel` = the same default as `{id, name?}`; `droppedEntries` = server >= 7.123.0, ALWAYS present
|
|
11018
|
+
there: the catalog entries THIS generation's read leg dropped one by one (an entry that does not pass the settings-schema
|
|
11019
|
+
`ModelEntry` shape; the rest of the catalog is served as usual). ABSENT = an earlier server (<= 7.122.x) — so the key is
|
|
11020
|
+
optional here (the SDK's supported server floor is 3.0.0); `[]` = the engine says nothing was dropped (also the env lane,
|
|
11021
|
+
where no catalog is read), which is NOT the same as absent (the engine cannot say).
|
|
11022
|
+
# 🔴 封闭 + `defaultModel` 补登记(census 批2 第三段,2026-07-30):铸造点
|
|
11023
|
+
# `routes/capabilities.ts` 三键字面量。`defaultModel`([865]③ id/name 撕裂消解,server
|
|
11024
|
+
# 已发多版)SDK `models.list()` 的返回类型早就带,**spec 是唯一没登记的一侧** —— 生成式
|
|
11025
|
+
# 消费方对它全瞎。`name` 条件(目录无命中即省略),`id` 恒在。
|
|
11026
|
+
# 18.2.0:信封升为具名 schema(此前内联在 `GET /v1/models` 的 200 上),新键 `droppedEntries`(server >= 7.123.0)挂在上面,**不进 required**。
|
|
11027
|
+
additionalProperties: false
|
|
11028
|
+
required: [models, default, defaultModel]
|
|
11029
|
+
properties:
|
|
11030
|
+
models:
|
|
11031
|
+
type: array
|
|
11032
|
+
items: { $ref: '#/components/schemas/ModelInfo' }
|
|
11033
|
+
default: { type: string, description: "deployment default model id (display-only; legacy id-form, byte-stable)" }
|
|
11034
|
+
defaultModel:
|
|
11035
|
+
type: object
|
|
11036
|
+
additionalProperties: false
|
|
11037
|
+
required: [id]
|
|
11038
|
+
properties:
|
|
11039
|
+
id: { type: string }
|
|
11040
|
+
name: { type: string, description: 'the catalog @handle of the default model; omitted when the catalog has no match (env single-model lane).' }
|
|
11041
|
+
droppedEntries:
|
|
11042
|
+
type: array
|
|
11043
|
+
items: { $ref: '#/components/schemas/DroppedEntry' }
|
|
11044
|
+
description: >
|
|
11045
|
+
server >= 7.123.0 (settings-schema >= 10.1.0), always present there; ABSENT = an earlier server. The catalog entries the read leg
|
|
11046
|
+
dropped from THIS generation (an entry that does not pass the `ModelEntry` shape) so a shell / admin panel can tell "which entry
|
|
11047
|
+
I wrote did the engine not take, and why" without re-judging the schema. Rows carry an index, a closed reason word and (when
|
|
11048
|
+
disclosable) a name / id — NEVER free text (the schema diagnostics, the entry value and any Record key stay in the server log).
|
|
11049
|
+
🔴 SAME GENERATION as `models`: both are the two faces of one catalog generation and commit together. When a center candidate's
|
|
11050
|
+
model plane is refused as a group (for example the default model is not in the catalog), or the candidate has no enabled entry at all
|
|
11051
|
+
(survivors and dropped rows both count by the `enabled` each row wrote; a dropped row whose `enabled` cannot be read counts as enabled),
|
|
11052
|
+
`models` and `droppedEntries` both stay on the previous generation — the key does NOT report the entries of the candidate that did not
|
|
11053
|
+
land (why it did not land: `/health.modelRefusals`). So a disabled dropped entry shows up only in a catalog that has an enabled entry and whose model
|
|
11054
|
+
plane landed. Different question from `/health.modelRefusals` (which names the models this box does NOT serve, with the engine's refusal code):
|
|
11055
|
+
this key lists what the read leg dropped, including nameless and disabled rows.
|
|
11056
|
+
Upgrade window (as it is): an on-disk LKG written by server <= 7.122.x only recorded the dropped entries that had a name AND were
|
|
11057
|
+
enabled; while serving from it with the center still unreachable this key lists only those rows (possibly `[]`) and the first pull after the
|
|
11058
|
+
center is reachable fills it in. An unknown `reasonCode` word reads as "dropped, reason unknown".
|
|
11059
|
+
|
|
11060
|
+
DroppedEntry:
|
|
11061
|
+
type: object
|
|
11062
|
+
description: >
|
|
11063
|
+
One row of `ModelsResponse.droppedEntries` (server >= 7.123.0): a catalog entry the read leg dropped. `index` = the entry's original
|
|
11064
|
+
position in the `models` array of the catalog document read this time (the local lane = its place in `config.d/models.json`; the
|
|
11065
|
+
center lane = the catalog the center sent this worker) — the same coordinate as the server's `models.<index>` log line.
|
|
11066
|
+
`identity` is optional: absent when none of the three keys is disclosable.
|
|
11067
|
+
additionalProperties: false
|
|
11068
|
+
required: [index, reasonCode]
|
|
11069
|
+
properties:
|
|
11070
|
+
index: { type: integer, minimum: 0 }
|
|
11071
|
+
reasonCode: { $ref: '#/components/schemas/DroppedEntryReasonCode' }
|
|
11072
|
+
identity: { $ref: '#/components/schemas/DroppedEntryIdentity' }
|
|
11073
|
+
|
|
11074
|
+
DroppedEntryReasonCode:
|
|
11075
|
+
type: string
|
|
11076
|
+
enum: [entry-schema-invalid, entry-key-invalid, entry-unreadable]
|
|
11077
|
+
description: >
|
|
11078
|
+
Why the read leg dropped a catalog entry (server >= 7.123.0). The words are settings-schema's closed `DROPPED_ENTRY_REASON_CODES`, passed through
|
|
11079
|
+
verbatim (the server neither hand-copies nor rewrites them; a new word in the package is a compile error there, forcing an explicit decision).
|
|
11080
|
+
`entry-schema-invalid` = the entry did not pass its own schema; `entry-key-invalid` = a Record-shaped collection's key did not pass the key schema
|
|
11081
|
+
(the catalog is an array, so this word does not appear on `droppedEntries` today — keep it in the switch anyway); `entry-unreadable` = the judging
|
|
11082
|
+
threw (a pathological accessor; the engine never carries what it threw). Read an unknown word as "dropped, reason unknown".
|
|
11083
|
+
|
|
11084
|
+
DroppedEntryIdentity:
|
|
11085
|
+
type: object
|
|
11086
|
+
description: >
|
|
11087
|
+
The disclosable identity of a dropped entry (settings-schema's entry-identity shape). `name` / `id` appear only when they are DISCLOSABLE identifiers
|
|
11088
|
+
(allow-listed characters, no secret shape, no URL userinfo — the server asks again at the exit); a non-disclosable one is simply absent, NOT masked (a masked
|
|
11089
|
+
string is no longer an identity). `enabled` is the boolean the entry wrote itself (a disabled dropped entry is listed with `enabled: false`). With none of the
|
|
11090
|
+
three keys the whole `identity` is absent — an empty object never reaches the wire, hence minProperties: 1.
|
|
11091
|
+
additionalProperties: false
|
|
11092
|
+
minProperties: 1
|
|
11093
|
+
properties:
|
|
11094
|
+
name: { type: string }
|
|
11095
|
+
id: { type: string }
|
|
11096
|
+
enabled: { type: boolean }
|
|
11097
|
+
|
|
10940
11098
|
ModelInfo:
|
|
10941
11099
|
type: object
|
|
10942
11100
|
description: >
|
|
@@ -12848,8 +13006,9 @@ components:
|
|
|
12848
13006
|
REQUIRED iff `decision==="edit"` (FORBIDDEN otherwise → 400).
|
|
12849
13007
|
🔴 THE BODY KEY SET IS CLOSED (server >= 7.86.0 / S-438): an unrecognised top-level key is refused with
|
|
12850
13008
|
400 `request.body_shape` plus the `unknownKeys` / `unsupportedKeys` machine tables — refused rather
|
|
12851
|
-
than dropped, because a misspelled `permissionModeAfter` would otherwise silently
|
|
12852
|
-
|
|
13009
|
+
than dropped, because a misspelled `permissionModeAfter` would otherwise silently fold to `default`
|
|
13010
|
+
(the task keeps asking before each write after its plan was approved) while the caller believes the
|
|
13011
|
+
mode was settled.
|
|
12853
13012
|
required: [decision]
|
|
12854
13013
|
additionalProperties: false
|
|
12855
13014
|
properties:
|
|
@@ -12860,18 +13019,35 @@ components:
|
|
|
12860
13019
|
type: string
|
|
12861
13020
|
enum: [default, acceptEdits]
|
|
12862
13021
|
description: >
|
|
12863
|
-
server >= 7.86.0 (S-433, P1
|
|
12864
|
-
|
|
12865
|
-
|
|
12866
|
-
|
|
12867
|
-
|
|
12868
|
-
|
|
13022
|
+
server >= 7.86.0 (S-433, P1) — WHICH PERMISSION MODE THIS TASK CONTINUES IN once the plan is approved.
|
|
13023
|
+
`acceptEdits` = writes stop asking; `default` = keep asking (AND is the folded value when the key is
|
|
13024
|
+
absent, so an older shell executes plans unchanged). The decision writes the mode back into the task's
|
|
13025
|
+
stored submit body, so every later park -> resume continues in it and never falls back to plan.
|
|
13026
|
+
🔴 server >= 7.122.0 — ONE JUDGE, ONE SOURCE: plan is only the engine's `permissionMode:"plan"`. Since 7.122.0
|
|
13027
|
+
the service adds no read-only clamp of its own, so there is none to lift: the tool table equals `default`'s,
|
|
13028
|
+
and a write or any non-read-only call is asked (somebody can answer) or refused (nobody can) AT CALL TIME by
|
|
13029
|
+
the engine's plan gate. A run's mode word has ONE source, the stored submit body; its two writers are the submit door
|
|
13030
|
+
and this write-back. A decision that carries the plan out of plan mode — `approve` (the original plan) or
|
|
13031
|
+
`edit` (the person's revised plan; the engine proceeds with it) — writes this key back (absent => `default`);
|
|
13032
|
+
only `reject` (the review goes back to redo the plan, plan mode stays) does not. Before 7.122.0 the service
|
|
13033
|
+
also mapped plan to read-only hands; this key was added in 7.86.0 because, before it, approving a plan was a
|
|
13034
|
+
BLANK CHEQUE (the plan was approved while the read-only clamp stayed on and every write kept asking); and on
|
|
13035
|
+
7.86.0-7.121.x `edit` + this key was a 400 while `edit` itself wrote back `plan`, the continuation still held
|
|
13036
|
+
by the read-only hands. All of that is gone since 7.122.0.
|
|
13037
|
+
(A deployment's `AUTONOMY=read-only` static fence is a separate thing: since 7.122.0 it is all the service's governance
|
|
13038
|
+
layer re-folds on each resume, it has nothing to do with approving a plan, and approval does not lift it.)
|
|
13039
|
+
🔴 THREE 400s, each with its own code (match by CODE, not by sentence — the two `request.field_conflict`
|
|
13040
|
+
sentences were reworded in 7.122.0, codes unchanged): a value outside the two-word closed set =>
|
|
12869
13041
|
`request.field_invalid` (ZERO widening arm — this bit decides whether the model has hands after
|
|
12870
13042
|
approval, so folding a misspelling into either mode is a silent downgrade on the security axis);
|
|
12871
|
-
sending it with `
|
|
12872
|
-
|
|
12873
|
-
settled); sending it for a task
|
|
12874
|
-
|
|
13043
|
+
sending it with `reject` => `request.field_conflict`, server sentence `permissionModeAfter is only valid with a
|
|
13044
|
+
decision that carries the plan out ('approve' or 'edit'; got 'reject')` (a silent drop there would let the caller
|
|
13045
|
+
believe the mode was settled); sending it for a task whose STORED permission mode is not `plan` (the model
|
|
13046
|
+
entered plan mode itself, so approving returns it to the mode it was in before planning) =>
|
|
13047
|
+
`request.field_conflict`, server sentence `permissionModeAfter does not apply to this task: it was not
|
|
13048
|
+
started in plan mode (its stored permission mode is not "plan"), so approving the plan returns it to the mode
|
|
13049
|
+
it was in before planning`. A task STARTED in plan mode is one the request put there, or one an operator
|
|
13050
|
+
`AUTONOMY=plan` stamped at the submit door (its stored word is `plan`): the key is accepted for both.
|
|
12875
13051
|
⚠️ DIRECT-DOOR deployments: this key rides the HMAC envelope's TRAILING EXTENSION OBJECT (server
|
|
12876
13052
|
7.87.0: `{answer?, permissionModeAfter?}`, present keys in lexicographic order; 7.86.0's bare
|
|
12877
13053
|
trailing slot is DELETED with zero double-read) ⇒ a signer must sign the new shape, and mixed
|
|
@@ -13717,6 +13893,14 @@ components:
|
|
|
13717
13893
|
`writeFace: open`; read `capabilities.taskWriteFaceOpen` first); (2) server >= 7.106.0 / S-895: `inheritEnv: "all"` on a
|
|
13718
13894
|
hosted deployment (`REQUIRE_PRINCIPAL=true`; reach = the hosted posture only; read `capabilities.projectContext` first).
|
|
13719
13895
|
Remove the key (or send `inheritEnv: "scrub"`) and resend. Resume legs fold it into 409 `resume_blocked_by_policy`.
|
|
13896
|
+
🔴 `request.autonomy_lane_refused` (422, server >= 7.122.0): the deployment's operator `AUTONOMY` does not take tasks on this LANE.
|
|
13897
|
+
Today's only trigger is `AUTONOMY=plan` × `POST /v1/leader` — plan leaves plan mode only through a person approving the plan (plan
|
|
13898
|
+
review), a leader task's workers have no plan review channel, so the refusal is at the door and NO run is created (a replay with the
|
|
13899
|
+
same `Idempotency-Key` gets the same 422 and does not consume the key). Same family as `host_posture_refused` but a different axis:
|
|
13900
|
+
that one is the hosted / tenant posture axis (remove the key and resend); this one is the AUTONOMY axis (nothing to remove — submit
|
|
13901
|
+
as a run via `POST /v1/runs`, or ask the operator for `AUTONOMY=read-only` / `ask`, under which leader tasks run). Read the live
|
|
13902
|
+
config: a hot change takes effect on the next request; read `GET /v1/policy` `autonomy` beforehand (the `capabilities.leader` bit
|
|
13903
|
+
reads false on such a deployment).
|
|
13720
13904
|
error: { type: string }
|
|
13721
13905
|
errorMessage: { type: string }
|
|
13722
13906
|
activeTaskId:
|
|
@@ -14455,7 +14639,9 @@ components:
|
|
|
14455
14639
|
bypass-IMMUNE (not releasable).
|
|
14456
14640
|
CLOSED on the gate record (screened with core `isAskClass`). `bypassPermissions` releases only the ten RELEASABLE classes
|
|
14457
14641
|
(`transcript_write` / `rule_unreadable` / `probe` / `write_protection` / `tool_marks_mcp` / `tool_marks_a2a` /
|
|
14458
|
-
`artifact_shared_read` / `mode` / `unstated` / `ordinary`)
|
|
14642
|
+
`artifact_shared_read` / `mode` / `unstated` / `ordinary`) — on every face — plus, from server >= 7.122.0 / core 7.47.0, an eleventh on the SHELL
|
|
14643
|
+
face only: `write_protection_unresolved` (core `releasableAskClassesFor(face)`: shell 11, other faces 10; on the file tools that class is
|
|
14644
|
+
refused, `deniedBy: mode`); every other class (deployment-authored `operator_forced`, ask / org rules, hook,
|
|
14459
14645
|
ancestor, content question, …) asks under every mode.
|
|
14460
14646
|
ModeRelease:
|
|
14461
14647
|
type: object
|
|
@@ -14477,8 +14663,19 @@ components:
|
|
|
14477
14663
|
mandate: { $ref: '#/components/schemas/PersistedRuleMandate' }
|
|
14478
14664
|
reason:
|
|
14479
14665
|
type: string
|
|
14480
|
-
enum: [rule_unreadable]
|
|
14481
|
-
description:
|
|
14666
|
+
enum: [rule_unreadable, write_protection_unresolved]
|
|
14667
|
+
description: >
|
|
14668
|
+
WHAT the release went over — one word: the FIRST member (in core `MODE_RELEASE_REASONS` array order) that the ask's class
|
|
14669
|
+
set holds; ABSENT when the set holds none. CLOSED set — the server screens it with core `isModeReleaseReason`, so a word
|
|
14670
|
+
outside it withholds the whole `gate` from the frame (and a consumer that dispatches on the word must learn each new one).
|
|
14671
|
+
`rule_unreadable` = the release went over a rule this call could not be read against (the rule store was unreadable — a
|
|
14672
|
+
security-axis fail-open direction the server discloses on its own).
|
|
14673
|
+
`write_protection_unresolved` (server >= 7.122.0 / core 7.47.0) = the release went over a write whose target the
|
|
14674
|
+
write-protection judge could not RESOLVE (whether it lands on the protected table is unknown). It is released on the SHELL
|
|
14675
|
+
face only: a caller-supplied tool whose wire name is exactly `Bash` or `Monitor` and which declares a write-path target,
|
|
14676
|
+
under `bypassPermissions`; on the file tools the same unresolved write is still refused (`deniedBy: mode`). The engine's
|
|
14677
|
+
own `Bash` / `Monitor` cannot mint this class and the server mounts no such tool — it comes from a caller-embedded tool of
|
|
14678
|
+
those names. Before server 7.122.0 / core 7.47.0 the set was `rule_unreadable` alone.
|
|
14482
14679
|
|
|
14483
14680
|
GateClassifierAttribution:
|
|
14484
14681
|
# sdk 9.5.0:具名 —— 同一份形挂在 `GateDisposition` 的两只臂上,内联会立刻是两份会各自漂的镜像。
|
|
@@ -17871,13 +18068,16 @@ components:
|
|
|
17871
18068
|
🔴 Its arrival means the RUN IS STILL ALIVE — the 15-minute stream cap fired. The correct handling is to
|
|
17872
18069
|
RECONNECT with `Last-Event-ID` and keep reading (the durable leg stamps `id:` on every frame); rendering
|
|
17873
18070
|
it as a terminal would declare a live task dead. `done` / `failed` are the terminal arms; this one is not.
|
|
17874
|
-
Known `errorCode`: `STREAM_MAX_DURATION` (
|
|
17875
|
-
|
|
18071
|
+
Known `errorCode`: `STREAM_MAX_DURATION` (the 15-minute cap) · `draining` (server >= 7.122.0: the instance entered drain / is being
|
|
18072
|
+
replaced — each of the eight read-only subscription streams gets this frame at the moment drain begins and is then closed by the server;
|
|
18073
|
+
same code and sentence as the billable-submit 503 `draining`, same reconnect protocol: reconnect with `Last-Event-ID`, the replacement
|
|
18074
|
+
instance serves it; NOT a run failure; the same reason family as the cap — the server closes a stream for flow control)
|
|
18075
|
+
(open set — branch on the code, degrade unknown codes to the generic "reconnectable stream-control signal").
|
|
17876
18076
|
additionalProperties: false
|
|
17877
18077
|
required: [type, errorCode]
|
|
17878
18078
|
properties:
|
|
17879
18079
|
type: { const: error }
|
|
17880
|
-
errorCode: { type: string, description: 'STREAM_MAX_DURATION (open set).' }
|
|
18080
|
+
errorCode: { type: string, description: 'STREAM_MAX_DURATION | draining (server >= 7.122.0) (open set).' }
|
|
17881
18081
|
message: { type: string }
|
|
17882
18082
|
Event_question:
|
|
17883
18083
|
type: object
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/sdk",
|
|
3
|
-
"version": "18.
|
|
3
|
+
"version": "18.2.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",
|
|
@@ -52,6 +52,6 @@
|
|
|
52
52
|
"prepublishOnly": "rm -f tsconfig.tsbuildinfo && npm run build && npm run typecheck --workspaces=false --prefix ../.. && npm test --workspaces=false --prefix ../.. && npm run prepack"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@sema-agent/settings-schema": "^
|
|
55
|
+
"@sema-agent/settings-schema": "^10.1.1"
|
|
56
56
|
}
|
|
57
57
|
}
|