@sema-agent/sdk 9.3.0 → 9.5.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 +46 -1
- package/dist/errors.d.ts +23 -10
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +29 -15
- package/dist/errors.js.map +1 -1
- package/dist/events.d.ts +174 -24
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +262 -13
- package/dist/types.d.ts.map +1 -1
- package/openapi.yaml +449 -14
- package/package.json +1 -1
package/openapi.yaml
CHANGED
|
@@ -2670,15 +2670,19 @@ paths:
|
|
|
2670
2670
|
— the workflow run's record carries no readable `parks[]` list (the ENGINE's own park-ownership
|
|
2671
2671
|
ledger, and the single source this lane joins the caller's checkpoint against). A record written by
|
|
2672
2672
|
an engine older than 7.17.0 does not carry the key at all, or one entry is damaged and the whole list
|
|
2673
|
-
cannot be read;
|
|
2674
|
-
(`workflow.park_truth_unreadable` / `parks_unreadable`, or `workflow.park_binding_broken`), so the
|
|
2673
|
+
cannot be read; the redemption keys this lane would need are therefore not on the record, so the
|
|
2675
2674
|
decision is STRUCTURALLY UNDELIVERABLE and this lane refuses loudly rather than answer a 200 nothing
|
|
2676
2675
|
could redeem. Body carries `runId` (the WORKFLOW run) and NO `taskId` (same two-field shape as the
|
|
2677
2676
|
SEVENTH group). SDK → `DecideWorkflowParksUnreadableError` (a `DecideError` subclass, NOT a
|
|
2678
2677
|
`DecideWorkflowHostError` — see its class doc for why). 🔴 RECOVERY IS THE OPPOSITE of the SEVENTH
|
|
2679
|
-
group:
|
|
2680
|
-
|
|
2681
|
-
|
|
2678
|
+
group: not a retry of this decide and not waiting for the host to park again — RESUME THE RUN
|
|
2679
|
+
(`runId`). Whether that resume is ADMITTED is the engine's answer, not this lane's: admission weighs
|
|
2680
|
+
the record, the journal and the record's own parked agent rows together and proves each candidate, so
|
|
2681
|
+
a caller must neither pre-filter recovery candidates on this code nor promise the user it will work.
|
|
2682
|
+
🔴 CORRECTED at server 7.78.0 / core 7.18.0: this text used to say the engine refuses to resume such a
|
|
2683
|
+
record and the only recovery was to start a NEW run — core 7.18.0 falsified that, and the old advice
|
|
2684
|
+
abandoned recoverable runs. Once admission completes the engine writes `parks` onto the record, and
|
|
2685
|
+
the next decide takes the ordinary arm. The card stays PENDING throughout (nothing is forged). ⚰️ This code REPLACES the 7.71.0 code `decide.workflow_park_identity_lost`
|
|
2682
2686
|
(retired at this same 7.75.0 — a store size-degrade step stopped keeping a SECOND copy of a parked
|
|
2683
2687
|
row's recovery identity once `parks[]` became the engine's single source, so the state that old code
|
|
2684
2688
|
named is now structurally unreachable). That retired code was NEVER modeled by this SDK (it went
|
|
@@ -8151,6 +8155,80 @@ components:
|
|
|
8151
8155
|
type: array
|
|
8152
8156
|
description: 'The nested ctx.workflow group tree (roots only — children nest recursively). Empty when the script used no nesting.'
|
|
8153
8157
|
items: { $ref: '#/components/schemas/WorkflowGroupNode' }
|
|
8158
|
+
parks:
|
|
8159
|
+
type: array
|
|
8160
|
+
description: >
|
|
8161
|
+
core 7.17.0 (#652) / server >= 7.74.0 — the engine's own PARK RESPONSIBILITY table for this run
|
|
8162
|
+
(detail face only; the list row has no such key).
|
|
8163
|
+
🔴 `undefined` AND `[]` ARE TWO DIFFERENT THINGS: the WHOLE KEY ABSENT means an OLDER ENGINE wrote
|
|
8164
|
+
this record (or the store's projection stripped it), so THIS FIELD ALONE cannot prove whether parks
|
|
8165
|
+
exist; `parks: []` is a POSITIVE FACT — "this run has no park". Never fold one into the other; the
|
|
8166
|
+
reading is `"parks" in run`.
|
|
8167
|
+
🔴 THIS KEY DECIDES NOTHING ABOUT WHETHER THE RUN CAN BE RESUMED — in EITHER direction. Resume
|
|
8168
|
+
admission is the ENGINE's: it weighs the record's `parks` (when present), the journal's `parked`
|
|
8169
|
+
entries and the record's own `status:"parked"` agent rows together, proves each candidate against the
|
|
8170
|
+
checkpoint store, and has refusal arms this read face cannot see. A consumer must not drop a run from
|
|
8171
|
+
its recovery candidates because this key is absent (that abandons recoverable runs), and must not
|
|
8172
|
+
promise recovery because it is present.
|
|
8173
|
+
⚠️ This description deliberately does NOT restate the admission algorithm: a mirror of someone else's
|
|
8174
|
+
rule goes stale (this very text asserted "absent => the engine refuses to resume, start a new run"
|
|
8175
|
+
between server 7.75.0 and 7.78.0, which core 7.18.0 falsified). The ONE bit that IS decisive on this
|
|
8176
|
+
face is `resumeAdmissionIncomplete`.
|
|
8177
|
+
⚠️ The `/decide` lane does still refuse such a record (the keys it must join against are derived in
|
|
8178
|
+
the admission pass and cannot be read off the record); its recovery verb is RESUME THIS RUN, not
|
|
8179
|
+
"start a new one". Two lanes, two predicates — never infer one from the other.
|
|
8180
|
+
🔴 KEYS ONLY — not a pending count and not a status (core's words): entries are replaced by
|
|
8181
|
+
`callKey` and are NEVER removed when a decision lands, so a listed token may already be resolved /
|
|
8182
|
+
expired / reaped. Never read `parks.length` as "how many approvals are waiting" (that is
|
|
8183
|
+
`GET /v1/approvals`).
|
|
8184
|
+
🔴 The redemption TOKEN is deliberately NOT projected: one GET would silently promote read access
|
|
8185
|
+
to decide access. `/decide` takes the token from the checkpoint row itself.
|
|
8186
|
+
items: { $ref: '#/components/schemas/WorkflowRunPark' }
|
|
8187
|
+
resumeAdmissionIncomplete:
|
|
8188
|
+
type: boolean
|
|
8189
|
+
enum: [true]
|
|
8190
|
+
description: >
|
|
8191
|
+
core 7.18.0 (#755) / server >= 7.78.0 — this RESUME record's admission did not complete.
|
|
8192
|
+
🔴 NEVER-FALSE: core DELETES the key the moment admission completes and never writes `false`, so the
|
|
8193
|
+
only reading is presence. ABSENT = admission completed, OR this is not a resume at all (the normal
|
|
8194
|
+
case) — absence asserts nothing.
|
|
8195
|
+
🔴 PRESENT => IT IS NOT A RESUME BASE: the engine refuses it whole (`admission_incomplete`) and
|
|
8196
|
+
derives no candidate from it. A face rendering resume candidates MUST carry this bit — dropping it
|
|
8197
|
+
turns a REFUSED record back into an admissible one (core's words; the projection obligation is
|
|
8198
|
+
word-for-word the same rank as `parks`). It does NOT fold into the absence of `parks`, which has
|
|
8199
|
+
its own two meanings (above).
|
|
8200
|
+
|
|
8201
|
+
WorkflowRunPark:
|
|
8202
|
+
# sdk 9.5.0:具名行形(同 `WiringManifestMcpEntry` 的裁定),并且**封闭** —— 服务端逐键挑出这四位,
|
|
8203
|
+
# 多出来的键意味着有人在别处手拼了第二份形(凭据位就是这样漏出去的)。
|
|
8204
|
+
type: object
|
|
8205
|
+
additionalProperties: false
|
|
8206
|
+
description: >
|
|
8207
|
+
One row of `WorkflowRun.parks` — the engine's park responsibility table, EXACTLY four keys because the
|
|
8208
|
+
server picks them key by key rather than spreading core's row.
|
|
8209
|
+
🔴 THE REDEMPTION TOKEN IS STRUCTURALLY ABSENT from this shape: core's row carries one (its own note
|
|
8210
|
+
says never log / never URL), and the read face leaves it in the store. So "I can read the park row"
|
|
8211
|
+
never means "I can decide it".
|
|
8212
|
+
required: [callKey, sessionId, originRunId]
|
|
8213
|
+
properties:
|
|
8214
|
+
callKey: { type: string, description: "Which call this park belongs to — joins `agents[].callKey`." }
|
|
8215
|
+
sessionId: { type: string, description: 'The parked CHILD session the host routes by.' }
|
|
8216
|
+
originRunId:
|
|
8217
|
+
type: string
|
|
8218
|
+
description: >
|
|
8219
|
+
Which run this park was MADE on. On an inherited entry it is NOT this run's id; and while
|
|
8220
|
+
`originUnconfirmed` is present it says which run the material BELONGS TO, not where it was seen.
|
|
8221
|
+
originUnconfirmed:
|
|
8222
|
+
type: boolean
|
|
8223
|
+
enum: [true]
|
|
8224
|
+
description: >
|
|
8225
|
+
core 7.18.0 (#757) / server >= 7.78.0 — NO journal has yet read or written a `parked` entry for this
|
|
8226
|
+
token.
|
|
8227
|
+
🔴 It PAIRS with `originRunId`: while present, that coordinate is UNCONFIRMED — core's contract,
|
|
8228
|
+
verbatim, "a consumer must not read it as confirmed". Projecting the coordinate and dropping this
|
|
8229
|
+
bit renders an unconfirmed coordinate as a confirmed one.
|
|
8230
|
+
🔴 NEVER-FALSE: upstream DELETES the key at confirmation and never writes `false`, so absence =
|
|
8231
|
+
confirmed, and rows written before 7.78.0 read identically (a true additive).
|
|
8154
8232
|
|
|
8155
8233
|
# ── B4 命名化(2026-07-31):以下 10 个 component 与 SDK resources/* 的同名导出类型 1:1;内容为
|
|
8156
8234
|
# 原端点内联 schema 的字节级搬运(零语义变更),使用点换 $ref。census 封闭注随迁。
|
|
@@ -8849,13 +8927,16 @@ components:
|
|
|
8849
8927
|
🔴 A SIXTH PROVENANCE (server >= 7.75.0 / S-252, same lane): a 409 `decide.workflow_parks_unreadable`
|
|
8850
8928
|
instead of the 200 above means the run record's `parks[]` — the engine's OWN park-ownership ledger,
|
|
8851
8929
|
and the only source this lane can join the caller's checkpoint against — cannot be read at all (an
|
|
8852
|
-
engine older than 7.17.0 never wrote the key, or one entry is damaged).
|
|
8853
|
-
|
|
8854
|
-
|
|
8855
|
-
|
|
8856
|
-
|
|
8857
|
-
|
|
8858
|
-
|
|
8930
|
+
engine older than 7.17.0 never wrote the key, or one entry is damaged). The redemption keys this lane
|
|
8931
|
+
needs are not on such a record, so it refuses rather than accept a decision it could never deliver.
|
|
8932
|
+
This is NOT the same failure as `decide.workflow_host_not_parked`: recovery is neither a retry nor
|
|
8933
|
+
waiting for a park — it is RESUMING the run named by `runId`, and whether that resume is admitted is the
|
|
8934
|
+
engine's answer, not this lane's. 🔴 CORRECTED at server 7.78.0 / core 7.18.0: this text used to say the
|
|
8935
|
+
engine refuses to resume such a record and that the only recovery was a NEW run — core 7.18.0 falsified
|
|
8936
|
+
that (admission does not decide on the record's `parks` key alone), and the old advice abandoned
|
|
8937
|
+
recoverable runs. SDK → a dedicated `DecideWorkflowParksUnreadableError` (NOT
|
|
8938
|
+
`DecideWorkflowHostError` — folding the two together would make "retry this decide" look like valid
|
|
8939
|
+
advice, when the action is to resume the run instead). This
|
|
8859
8940
|
code REPLACES the 7.71.0 code `decide.workflow_park_identity_lost`, retired at this same 7.75.0 and
|
|
8860
8941
|
never modeled by any released version of this SDK.
|
|
8861
8942
|
The durable approval-queue projection is UNCHANGED — no key marks the workflow origin on any read face.
|
|
@@ -9566,7 +9647,11 @@ components:
|
|
|
9566
9647
|
description: >
|
|
9567
9648
|
`GET /v1/sessions/:id/mcp` envelope. `asOf` = THIS materialization moment (ISO). `degraded:true` (servers
|
|
9568
9649
|
empty) ⇒ materialize timed out/failed (NOT "no MCP"). No MCP configured ⇒ `servers:[]` without `degraded`.
|
|
9650
|
+
server >= 7.77.0 adds the OPTIONAL top-level key `lastLegMcp` (see its own description) — zero new
|
|
9651
|
+
capability bit, read it as absent-by-default.
|
|
9569
9652
|
# 封闭(census 批2 第三段,2026-07-30):三个铸造臂(`routes/sessions.ts` 的空面板 / 超时 degraded / 正常)键集并集恰是这 3 键;degraded 只在超时臂铸。
|
|
9653
|
+
# sdk 9.4.0:第 4 键 `lastLegMcp`(server ≥7.77.0)—— 同一个铸造点上按调用方裁的可选顶层键,不在
|
|
9654
|
+
# 面板那张短 TTL 单飞缓存里(缓存键=场景×principal,与会话无关)。
|
|
9570
9655
|
required: [asOf, servers]
|
|
9571
9656
|
additionalProperties: false
|
|
9572
9657
|
properties:
|
|
@@ -9575,6 +9660,46 @@ components:
|
|
|
9575
9660
|
type: array
|
|
9576
9661
|
items: { $ref: '#/components/schemas/McpServerStatus' }
|
|
9577
9662
|
degraded: { type: boolean }
|
|
9663
|
+
lastLegMcp:
|
|
9664
|
+
type: object
|
|
9665
|
+
description: >
|
|
9666
|
+
server >= 7.77.0 — WHAT THIS SESSION ACTUALLY MOUNTED LAST TIME: the `mcp` section of the LAST
|
|
9667
|
+
`wiring_manifest` in the ledger of this session's most recent run. `servers` above answers "what
|
|
9668
|
+
does this worker's DEFAULT SCENARIO give you"; this answers "what did my last run get". The two
|
|
9669
|
+
may LEGITIMATELY differ (request-level MCP injection, a non-default scenario, a server that was
|
|
9670
|
+
down for that leg) — 🔴 this is NOT a merge and NOT a reconciliation: the server does not infer a
|
|
9671
|
+
difference, mints no `divergent` verdict key, and `servers[]` is unchanged to the byte. Judging the
|
|
9672
|
+
difference belongs to the consumer and to people.
|
|
9673
|
+
🔴 ABSENT ⇒ THE KEY IS NOT PRESENT (never `null`), and every reachable cause is INDISTINGUISHABLE
|
|
9674
|
+
on the wire — the only read is `"lastLegMcp" in panel`: this session has not run a leg yet / that
|
|
9675
|
+
leg's ledger rows are outside the retention window / that leg never pushed a `wiring_manifest`
|
|
9676
|
+
(engines <= 7.8) / that frame carried no roster section / this deployment has no runs ledger / the
|
|
9677
|
+
ledger read failed or timed out (the panel still answers 200 — an additive optional key must not
|
|
9678
|
+
give an existing read face a new way to fall over) / the leg has an owner who is not the caller and
|
|
9679
|
+
the caller is not an explicit operator (the key is withheld; the panel is NOT 404'd).
|
|
9680
|
+
⚠️ `"mcp": []` is NOT absence — a present empty array means "that leg declared no servers".
|
|
9681
|
+
🔴 FRESHNESS: the panel body rides a short-TTL single-flight cache keyed by scenario x principal
|
|
9682
|
+
(session-independent); this key is DELIBERATELY OUTSIDE it, so within one response `asOf` may come
|
|
9683
|
+
from the cache while this key was read just now — both timestamps are honest about their own half.
|
|
9684
|
+
additionalProperties: false
|
|
9685
|
+
required: [runId, at, mcp]
|
|
9686
|
+
properties:
|
|
9687
|
+
runId:
|
|
9688
|
+
type: string
|
|
9689
|
+
description: >
|
|
9690
|
+
That leg's run id (the anchor for GET /v1/runs/{id}/events; same reading as the session list
|
|
9691
|
+
face's `lastRunId` — both always point at the same row).
|
|
9692
|
+
at:
|
|
9693
|
+
type: string
|
|
9694
|
+
description: "The LEDGER timestamp (ISO) of that `wiring_manifest` event — NOT the panel's `asOf`."
|
|
9695
|
+
mcp:
|
|
9696
|
+
type: array
|
|
9697
|
+
description: >
|
|
9698
|
+
Verbatim that event's `data.mcp` — the SAME shape as `Event_wiring_manifest.mcp` down to the
|
|
9699
|
+
byte (zero new shape: one payload, a second wire). Rows missing `name`/`status` were already
|
|
9700
|
+
dropped individually at projection time, and the engine's free-text `error` was already
|
|
9701
|
+
stripped there.
|
|
9702
|
+
items: { $ref: '#/components/schemas/WiringManifestMcpEntry' }
|
|
9578
9703
|
|
|
9579
9704
|
SessionMemoryStatus:
|
|
9580
9705
|
type: object
|
|
@@ -9881,8 +10006,11 @@ components:
|
|
|
9881
10006
|
`workflow_host_unknown`, `workflow_host_not_parked`, and — server >= 7.75.0 / S-252 —
|
|
9882
10007
|
`workflow_parks_unreadable`): the WORKFLOW run's id. On the first three it is the RECOVERY HANDLE
|
|
9883
10008
|
(wait for the host session to park and re-decide, or resume that run directly); on
|
|
9884
|
-
`workflow_parks_unreadable` it
|
|
9885
|
-
|
|
10009
|
+
`workflow_parks_unreadable` it is ALSO a recovery handle but for a DIFFERENT verb — resume that run
|
|
10010
|
+
(admission is where the engine settles its park set), do not re-issue this decide against it; whether
|
|
10011
|
+
that resume is admitted is the engine's answer, not this code's.
|
|
10012
|
+
🔴 CORRECTED at server 7.78.0 / core 7.18.0: this text used to call it a run that cannot be resumed
|
|
10013
|
+
at all, to be abandoned in favour of a new one — that was true of core < 7.18.0 only.
|
|
9886
10014
|
🔴 NOT interchangeable with `taskId`: the workflow-child park lane mints no taskId at all (this
|
|
9887
10015
|
decision never landed on any run, so minting one would be a lie), and the other two decide lanes
|
|
9888
10016
|
mint no runId. Branch by `errorCode`, never fall back from one handle to the other.
|
|
@@ -9965,6 +10093,15 @@ components:
|
|
|
9965
10093
|
# (server `routes/tasks.ts` mint points x this union), which now runs on every build.
|
|
9966
10094
|
- $ref: '#/components/schemas/Event_text_end'
|
|
9967
10095
|
- $ref: '#/components/schemas/Event_tool_roster_delta'
|
|
10096
|
+
# sdk 9.4.0: `reasoning_end` — the REASONING twin of `text_end`, BYTE-IDENTICAL in shape (both are
|
|
10097
|
+
# `allOf: [SegmentEndFields]`, one wire concept, one shape). SERVER-MINTED (server >= 7.77.0): the
|
|
10098
|
+
# engine emits only `reasoning_delta`, so this frame's presence tracks the SERVER version, not core's.
|
|
10099
|
+
- $ref: '#/components/schemas/Event_reasoning_end'
|
|
10100
|
+
# sdk 9.5.0: the two frames core 7.18.0 added and server 7.78.0 forwards — `tool_disclosure` (#786,
|
|
10101
|
+
# the leg's DEFERRAL CENSUS, all three legs) and `tool_progress` (#741, a still-running call's
|
|
10102
|
+
# liveness tick, LIVE ONLY — never on the durable replay).
|
|
10103
|
+
- $ref: '#/components/schemas/Event_tool_disclosure'
|
|
10104
|
+
- $ref: '#/components/schemas/Event_tool_progress'
|
|
9968
10105
|
discriminator:
|
|
9969
10106
|
propertyName: type
|
|
9970
10107
|
mapping:
|
|
@@ -10010,6 +10147,9 @@ components:
|
|
|
10010
10147
|
approval_revoke: '#/components/schemas/Event_approval_revoke'
|
|
10011
10148
|
text_end: '#/components/schemas/Event_text_end'
|
|
10012
10149
|
tool_roster_delta: '#/components/schemas/Event_tool_roster_delta'
|
|
10150
|
+
reasoning_end: '#/components/schemas/Event_reasoning_end'
|
|
10151
|
+
tool_disclosure: '#/components/schemas/Event_tool_disclosure'
|
|
10152
|
+
tool_progress: '#/components/schemas/Event_tool_progress'
|
|
10013
10153
|
|
|
10014
10154
|
# design/99 §E2 (SHIPPED, core TaskEventIdentity) — additive per-event identity on every CONTENT event (NOT on
|
|
10015
10155
|
# the lifecycle arms turn_end/compacted/suspended/done/failed). eventId = uuidv7 dedup/resume handle (the durable
|
|
@@ -10120,6 +10260,35 @@ components:
|
|
|
10120
10260
|
parentToolCallId: { type: string }
|
|
10121
10261
|
sourceTaskId: { type: string }
|
|
10122
10262
|
bgAgentId: { type: string }
|
|
10263
|
+
Event_reasoning_end:
|
|
10264
|
+
type: object
|
|
10265
|
+
description: >
|
|
10266
|
+
LIVE stream only (server >= 7.77.0) — the END-OF-SEGMENT signal for one REASONING segment, the twin of
|
|
10267
|
+
`text_end`. 🔴 SERVER-MINTED: core emits only `reasoning_delta`, so this frame's presence tracks the
|
|
10268
|
+
SERVER version, not core's. `content` is the segment's AUTHORITATIVE full text (the whole segment's
|
|
10269
|
+
deltas, through the SAME redactor as the durable leg) — and that is the reason the frame exists: a
|
|
10270
|
+
per-chunk `reasoning_delta` cannot see a credential that straddles two chunks, only the whole segment
|
|
10271
|
+
can. CONSUME IT BY REPLACING the deltas accumulated for that identity stream, not as a mere boundary
|
|
10272
|
+
signal; `reasoning_delta` itself is byte-for-byte unchanged.
|
|
10273
|
+
🔴 EMPTY SEGMENTS ARE NOT SENT (empty or all-whitespace): absence means "this segment has no
|
|
10274
|
+
replacement text", never "the segment has not ended" — a blank authoritative segment would make a
|
|
10275
|
+
consumer wipe what it already rendered.
|
|
10276
|
+
🔴 Segments are accounted PER IDENTITY STREAM (parentToolCallId / sourceTaskId / bgAgentId): on one SSE
|
|
10277
|
+
connection concurrent sub-agents interleave, so another stream's frame is NOT your boundary.
|
|
10278
|
+
🔴 The durable leg does not append it (the batched `reasoning` row carries the same final text, byte for
|
|
10279
|
+
byte), so GET /v1/runs/{id}/events never replays it.
|
|
10280
|
+
Shape is IDENTICAL to Event_text_end (one wire concept, one shape — the server mints both through one
|
|
10281
|
+
`segmentEndFields`); the only difference between the two frames is the empty-segment predicate.
|
|
10282
|
+
allOf: [{ $ref: '#/components/schemas/EventIdentity' }]
|
|
10283
|
+
additionalProperties: false # 封闭 + identity 本地镜像:见 Event_reasoning 处的长注
|
|
10284
|
+
required: [type, content]
|
|
10285
|
+
properties:
|
|
10286
|
+
type: { const: reasoning_end }
|
|
10287
|
+
content: { type: string }
|
|
10288
|
+
eventId: { type: string }
|
|
10289
|
+
parentToolCallId: { type: string }
|
|
10290
|
+
sourceTaskId: { type: string }
|
|
10291
|
+
bgAgentId: { type: string }
|
|
10123
10292
|
Event_tool_start:
|
|
10124
10293
|
type: object
|
|
10125
10294
|
allOf: [{ $ref: '#/components/schemas/EventIdentity' }]
|
|
@@ -10283,12 +10452,25 @@ components:
|
|
|
10283
10452
|
required: [kind]
|
|
10284
10453
|
properties:
|
|
10285
10454
|
kind: { const: allowed }
|
|
10455
|
+
classifier:
|
|
10456
|
+
allOf: [{ $ref: '#/components/schemas/GateClassifierAttribution' }]
|
|
10457
|
+
description: >
|
|
10458
|
+
server >= 7.78.0 (core 7.18.0 #742) — the classification's model attribution. It rides BOTH arms
|
|
10459
|
+
(a classification ends either way, allow or deny), which is why this key is mirrored on the deny
|
|
10460
|
+
arm below. Full reading in `GateClassifierAttribution`.
|
|
10286
10461
|
- type: object
|
|
10287
10462
|
additionalProperties: false
|
|
10288
10463
|
required: [kind, deniedBy]
|
|
10289
10464
|
properties:
|
|
10290
10465
|
kind: { const: denied }
|
|
10291
10466
|
deniedBy: { $ref: '#/components/schemas/DeniedBy' }
|
|
10467
|
+
classifier:
|
|
10468
|
+
allOf: [{ $ref: '#/components/schemas/GateClassifierAttribution' }]
|
|
10469
|
+
description: >
|
|
10470
|
+
server >= 7.78.0 (core 7.18.0 #742) — the same member as on the allow arm, same shape, same
|
|
10471
|
+
reading (see `GateClassifierAttribution`). Orthogonal to the sibling `cause`: `cause` says WHAT
|
|
10472
|
+
SHAPE this deny was, this key says WHICH MODEL decided — an inherited chain carries a `cause`
|
|
10473
|
+
with no attribution seat, so the two can appear apart.
|
|
10292
10474
|
cause:
|
|
10293
10475
|
type: string
|
|
10294
10476
|
description: >-
|
|
@@ -10302,6 +10484,52 @@ components:
|
|
|
10302
10484
|
— branch the two known words and keep a default arm. Absent = this deny was not a classifier-fault
|
|
10303
10485
|
shape (policy / person / rule refused); never read absence as "classifier healthy".
|
|
10304
10486
|
|
|
10487
|
+
GateClassifierAttribution:
|
|
10488
|
+
# sdk 9.5.0:具名 —— 同一份形挂在 `GateDisposition` 的两只臂上,内联会立刻是两份会各自漂的镜像。
|
|
10489
|
+
type: object
|
|
10490
|
+
additionalProperties: false
|
|
10491
|
+
description: >
|
|
10492
|
+
WHICH MODEL decided one auto-mode classification (core 7.18.0 #742 `AutoModeClassifierRound`,
|
|
10493
|
+
server >= 7.78.0): the rung it was FOR, the rung that ANSWERED, and — only when the ladder actually
|
|
10494
|
+
MOVED — where it left, where it landed and why.
|
|
10495
|
+
🔴 ABSENT READS **UNKNOWN**, NEVER "the seat answered" (core's words). "The seat answered" is this
|
|
10496
|
+
member PRESENT with `fallback` ABSENT — the two are distinguishable on the wire. The three causes of
|
|
10497
|
+
the member being absent are NOT distinguishable from the record: no classification happened; one ran on
|
|
10498
|
+
a decider given no candidate ladder (it can name no model); or one ran on an ANCESTOR's inherited
|
|
10499
|
+
chain, which carries the FORM but has no attribution seat yet.
|
|
10500
|
+
🔴 NOT PERSISTED into the durable row (same as core): it is an observation of HOW this gate pass was
|
|
10501
|
+
decided, not a terminal fact. It appears on `tool_end.gate` and on the two raw replay legs.
|
|
10502
|
+
🔴 A record failing core's invariant I6 is withheld WHOLE by the server, so every attribution that
|
|
10503
|
+
reaches a consumer has two non-empty model ids, `fallback.to === modelUsed`, and a cause inside the
|
|
10504
|
+
closed set.
|
|
10505
|
+
required: [modelRequested, modelUsed]
|
|
10506
|
+
properties:
|
|
10507
|
+
modelRequested: { type: string, description: "The ladder's FIRST rung — the seat this classification was for." }
|
|
10508
|
+
modelUsed:
|
|
10509
|
+
type: string
|
|
10510
|
+
description: >
|
|
10511
|
+
The rung whose answer the gate ACTED ON; where no candidate ruled, the last rung ATTEMPTED (stated,
|
|
10512
|
+
never implied by absence).
|
|
10513
|
+
fallback:
|
|
10514
|
+
type: object
|
|
10515
|
+
additionalProperties: false
|
|
10516
|
+
required: [from, to, cause]
|
|
10517
|
+
description: >
|
|
10518
|
+
Present EXACTLY when the ladder MOVED to reach `modelUsed`; ABSENT = the first rung answered
|
|
10519
|
+
("the seat answered"). This is the one place on this shape where an absence IS an assertion.
|
|
10520
|
+
properties:
|
|
10521
|
+
from: { type: string, description: 'The rung it left.' }
|
|
10522
|
+
to: { type: string, description: 'The rung it arrived at — ALWAYS equal to `modelUsed` (core invariant I6).' }
|
|
10523
|
+
cause:
|
|
10524
|
+
type: string
|
|
10525
|
+
enum: [error, timeout, parse_error]
|
|
10526
|
+
description: >
|
|
10527
|
+
Why the ladder moved: `error` (that rung threw / rejected), `timeout` (the round-trip cap),
|
|
10528
|
+
`parse_error` (it answered outside the verdict contract).
|
|
10529
|
+
🔴 TRULY CLOSED here, unlike most engine words on this wire: core's I6 screen calls an
|
|
10530
|
+
out-of-set cause a record DEFECT and the server withholds a defective record whole, so an
|
|
10531
|
+
unknown word reaches a consumer as an ABSENT `gate`, never as a strange value.
|
|
10532
|
+
|
|
10305
10533
|
GateOutcome:
|
|
10306
10534
|
type: object
|
|
10307
10535
|
additionalProperties: false
|
|
@@ -10881,6 +11109,27 @@ components:
|
|
|
10881
11109
|
already owns the single redaction mint point for it). The actionable cause is `errorCode`.
|
|
10882
11110
|
A row missing `name` or `status` is dropped individually — the other servers'' rows still ship.
|
|
10883
11111
|
items: { $ref: '#/components/schemas/WiringManifestMcpEntry' }
|
|
11112
|
+
hooks:
|
|
11113
|
+
type: array
|
|
11114
|
+
description: >
|
|
11115
|
+
core 7.18.0 (#789), server >= 7.78.0 — TENANT-visible: the hook seats THIS leg wired, one row per
|
|
11116
|
+
family, in core's declaration order. EFFECTIVE half only.
|
|
11117
|
+
🔴 PRESENT IFF at least one seat is wired — core NEVER emits an empty array, so "the key is here"
|
|
11118
|
+
means non-empty. 🔴 ABSENCE READS "this leg wired no hook RECORD of its own", NOT "no hook runs":
|
|
11119
|
+
a delegated child with no local record can still be screened (and refused) by an ANCESTOR's
|
|
11120
|
+
`preToolUse` through the gate's constraint fold, which this face deliberately does not call a hook
|
|
11121
|
+
of this leg. A row missing `family` or `owner` is dropped INDIVIDUALLY (same rule as `mcp[]`); all
|
|
11122
|
+
rows dropped => the key is absent. 🔴 EXCLUDED from `configFingerprint` (the record is a per-task
|
|
11123
|
+
seat), so two legs with the same fingerprint and different `hooks[]` are NOT in contradiction.
|
|
11124
|
+
items: { $ref: '#/components/schemas/WiringManifestHookEntry' }
|
|
11125
|
+
lsp:
|
|
11126
|
+
allOf: [{ $ref: '#/components/schemas/WiringManifestLspSeam' }]
|
|
11127
|
+
description: >
|
|
11128
|
+
core 7.18.0 (#789), server >= 7.78.0 — TENANT-visible: the LSP code-intelligence seam. EFFECTIVE
|
|
11129
|
+
half only. PRESENT IFF a manager seat resolved (`spec.lspManager ?? deps.lspManager`); a deployment
|
|
11130
|
+
that wires none reports nothing at all. The server never invents `mounted: false` when it cannot
|
|
11131
|
+
read the bit — the whole section goes absent instead (a minted false would read as "really not
|
|
11132
|
+
mounted").
|
|
10884
11133
|
governance:
|
|
10885
11134
|
type: object
|
|
10886
11135
|
additionalProperties: false
|
|
@@ -10930,6 +11179,104 @@ components:
|
|
|
10930
11179
|
parentToolCallId: { type: string }
|
|
10931
11180
|
sourceTaskId: { type: string }
|
|
10932
11181
|
bgAgentId: { type: string }
|
|
11182
|
+
Event_tool_disclosure:
|
|
11183
|
+
type: object
|
|
11184
|
+
description: >
|
|
11185
|
+
This leg's DEFERRAL CENSUS (server >= 7.78.0, core 7.18.0 #786): which mounted tools ship today as
|
|
11186
|
+
NAME-ONLY placeholders, which ones the model has activated, and which policy decided it.
|
|
11187
|
+
🔴 A DIFFERENT QUESTION FROM THE ROSTER: `wiring_manifest.tools` says WHICH TOOLS CAN BE CALLED; this
|
|
11188
|
+
frame says WHETHER ONE MUST BE FETCHED FIRST. A deferred name is ON the roster.
|
|
11189
|
+
🔴 ALL THREE LEGS (live SSE + durable ledger + resume replay), same as `tool_roster_delta`. The leg-start
|
|
11190
|
+
census is the FIRST frame after `wiring_manifest`; every later frame means the census CHANGED (an
|
|
11191
|
+
activation landed).
|
|
11192
|
+
🔴 WHOLE SNAPSHOT: `deferred` and `activated` are both complete — replace your copy, never merge.
|
|
11193
|
+
🔴 ABSENCE READINGS, three of them: (a) the WHOLE FRAME absent = "this leg deferred NOTHING" (a leg with
|
|
11194
|
+
an empty deferred set emits no frame at all) — NOT "this build has no such face" and NOT "unknown";
|
|
11195
|
+
(b) `thresholdPercent` absent = under `always` / `never` NO THRESHOLD WAS EVER CONSULTED — never read it
|
|
11196
|
+
as "the default percent"; (c) a RESUME leg's FIRST census may carry a non-empty `activated` (the engine
|
|
11197
|
+
reseeded it) — never read that as "this leg activated them".
|
|
11198
|
+
🔴 Half a census never reaches the wire: the server drops the WHOLE frame when any of the three required
|
|
11199
|
+
members is unreadable (half a table would read as "these are the only deferred ones").
|
|
11200
|
+
additionalProperties: false # 封闭 + identity 本地镜像:见 Event_reasoning 处的长注
|
|
11201
|
+
required: [type, policy, deferred, activated]
|
|
11202
|
+
properties:
|
|
11203
|
+
type: { const: tool_disclosure }
|
|
11204
|
+
policy:
|
|
11205
|
+
type: string
|
|
11206
|
+
description: >
|
|
11207
|
+
Which arm of `RunnerDeps.toolSearch` decided this (`always` / `never` / `auto` today). READ AS OPEN:
|
|
11208
|
+
the server passes it through verbatim and does not enumerate, so a new word must pass through your
|
|
11209
|
+
default arm.
|
|
11210
|
+
thresholdPercent:
|
|
11211
|
+
type: number
|
|
11212
|
+
description: >
|
|
11213
|
+
Under `auto`: the percent of the window the candidate set had to reach. ABSENT under `always` /
|
|
11214
|
+
`never` because no threshold was consulted — NEVER substitute a default.
|
|
11215
|
+
🔴 A FINITE NUMBER, NOT AN INTEGER: the engine's seat accepts any finite percent in [0, 100]
|
|
11216
|
+
(`{mode:"auto", thresholdPercent: 12.5}` is a legal deployment) and the server forwards it through
|
|
11217
|
+
a finite-number guard, verbatim. Typing it `integer` here would make a spec-validating consumer
|
|
11218
|
+
REJECT a legal frame, and the symptom ("this build has no census") is indistinguishable from the
|
|
11219
|
+
frame being absent. The range is NOT constrained here either: the seat enforces [0, 100] at parse
|
|
11220
|
+
time, the server re-derives nothing, and a bound this face does not enforce would be a second
|
|
11221
|
+
screen that can only disagree with the first.
|
|
11222
|
+
deferred:
|
|
11223
|
+
type: array
|
|
11224
|
+
items: { type: string }
|
|
11225
|
+
description: 'Every name-only placeholder on this leg (frozen at prepare, sorted). WHOLE snapshot.'
|
|
11226
|
+
activated:
|
|
11227
|
+
type: array
|
|
11228
|
+
items: { type: string }
|
|
11229
|
+
description: >
|
|
11230
|
+
The deferred names ACTIVE right now (the engine's state, not a record of commits; sorted, always a
|
|
11231
|
+
subset of `deferred`). WHOLE snapshot.
|
|
11232
|
+
# identity:两键 —— server 的 `identityFields` 只在这条臂上铸 eventId/parentToolCallId(本帧不在
|
|
11233
|
+
# live 腿那张四键白名单上),同 Event_compaction_outcome 的处置。
|
|
11234
|
+
eventId: { type: string }
|
|
11235
|
+
parentToolCallId: { type: string }
|
|
11236
|
+
Event_tool_progress:
|
|
11237
|
+
type: object
|
|
11238
|
+
description: >
|
|
11239
|
+
A LIVENESS TICK for a tool call that is STILL RUNNING (server >= 7.78.0, core 7.18.0 #741), minted
|
|
11240
|
+
between that call's `tool_start` and `tool_end` under the same ordering law as every other content
|
|
11241
|
+
frame; a child's ticks reach a parent under the same opt-in as those two
|
|
11242
|
+
(`TaskSpec.forwardSubagentEvents`).
|
|
11243
|
+
🔴 LIVE ONLY — NOT PERSISTED, NOT REPLAYED (core's `tool_progress.ephemeral`, same family as
|
|
11244
|
+
`task_progress` / `status`): `GET /v1/runs/{id}/events` has no such arm and a reconnect back-fills
|
|
11245
|
+
nothing. The DURABLE fact about how long a call took is `tool_end` — core states explicitly that
|
|
11246
|
+
`elapsedTimeSeconds` does NOT equal the `tool_end` duration (this clock starts when the call ENTERS
|
|
11247
|
+
EXECUTION, earlier than a shell command's spawn).
|
|
11248
|
+
🔴 THE FRAME'S ABSENCE IS NEVER EVIDENCE (core's `tool_progress.cadence`): at most one frame per second
|
|
11249
|
+
per call, and a call that finishes INSIDE one interval emits NONE. Never expect one per `tool_start`,
|
|
11250
|
+
and never use its presence to decide whether a call ran.
|
|
11251
|
+
🔴 `output` / `totalLines` / `totalBytes` RIDE OR STAY AWAY TOGETHER: present = "output has been
|
|
11252
|
+
observed", absent = "not one byte has been observed" (`sleep 3`; or an execution environment that does
|
|
11253
|
+
not stream — a buffered remote `exec` never invokes the output callbacks) — NEVER "unchanged since the
|
|
11254
|
+
last frame". The server projects the counters only when `output` itself is readable, so a counter never
|
|
11255
|
+
arrives without the text it counts.
|
|
11256
|
+
additionalProperties: false # 封闭 + identity 本地镜像:见 Event_reasoning 处的长注
|
|
11257
|
+
required: [type, toolCallId, toolName]
|
|
11258
|
+
properties:
|
|
11259
|
+
type: { const: tool_progress }
|
|
11260
|
+
toolCallId: { type: string, description: "The still-running call's id — joins its own `tool_start`/`tool_end`. The server drops the whole frame without it." }
|
|
11261
|
+
toolName: { type: string, description: 'The running tool name (the `tool_start` value verbatim).' }
|
|
11262
|
+
elapsedTimeSeconds:
|
|
11263
|
+
type: integer
|
|
11264
|
+
description: >
|
|
11265
|
+
Whole seconds this call has been running: floored, monotonic across its frames, ONE ORIGIN per call
|
|
11266
|
+
stamped by the mint. It does NOT equal the `tool_end` duration. ABSENT (rather than 0) when the
|
|
11267
|
+
server's finite-number guard could not read it — "the clock was unreadable" is not "zero seconds".
|
|
11268
|
+
output:
|
|
11269
|
+
type: string
|
|
11270
|
+
description: >
|
|
11271
|
+
The TAIL of what the command has written so far (stdout and stderr interleaved in arrival order),
|
|
11272
|
+
capped by the mint to a few trailing lines — a live pane, never a log.
|
|
11273
|
+
🔴 UNTRUSTED RAW, exactly like `tool_end.output`: the server has passed it through the SAME
|
|
11274
|
+
redactor, a consumer MAY bound it further before display, and it must NEVER be re-fed to a model
|
|
11275
|
+
(it is a moving, truncated window; the model already holds the full result).
|
|
11276
|
+
totalLines: { type: integer, description: 'Newlines observed so far (>= the tail''s own line count — the tail is only a window). Rides iff `output` does.' }
|
|
11277
|
+
totalBytes: { type: integer, description: 'Bytes observed BEFORE the tail cap, so it keeps growing after `output` stops being able to. Rides iff `output` does.' }
|
|
11278
|
+
eventId: { type: string }
|
|
11279
|
+
parentToolCallId: { type: string }
|
|
10933
11280
|
ToolRosterDelta:
|
|
10934
11281
|
type: object
|
|
10935
11282
|
description: >
|
|
@@ -12868,12 +13215,40 @@ components:
|
|
|
12868
13215
|
usedTokens: { type: integer }
|
|
12869
13216
|
windowTokens: { type: integer, description: 'autocompact 窗,不是模型上下文大小。' }
|
|
12870
13217
|
compactAtTokens: { type: integer }
|
|
13218
|
+
sections:
|
|
13219
|
+
type: array
|
|
13220
|
+
description: >
|
|
13221
|
+
core 7.18.0 (#790), server >= 7.78.0 — WHAT THIS LEG'S SYSTEM PROMPT IS MADE OF: one row per
|
|
13222
|
+
rendered pack section.
|
|
13223
|
+
🔴 NOT THE SAME COORDINATE SYSTEM AS `usedTokens` — NEVER SUBTRACT (core's contract, verbatim):
|
|
13224
|
+
`sections[].tokens` is a PREPARE-time estimate of the SYSTEM PROMPT from rendered character counts,
|
|
13225
|
+
while `usedTokens` is the engine's triggering input over the WHOLE conversation. So: never subtract
|
|
13226
|
+
the section sum from `usedTokens`, never compare one section against `compactAtTokens`, and never
|
|
13227
|
+
read a cross-frame change as "it grew" — the values FREEZE at prepare and every boundary on this leg
|
|
13228
|
+
re-reports the same set verbatim. The sum MAY exceed `usedTokens` (two quantities, not one ledger).
|
|
13229
|
+
🔴 THE WHOLE KEY ABSENT = this leg assembled NO section IR (some providers replace the prompt
|
|
13230
|
+
wholesale and hand back an opaque block) — NOT "every section weighs zero". An element missing
|
|
13231
|
+
`id`/`tokens` is dropped individually; all dropped => the key is absent.
|
|
13232
|
+
items: { $ref: '#/components/schemas/ContextUsageSection' }
|
|
12871
13233
|
# LIVE 腿(routes/tasks.ts)在这条臂上挂 identity;durable 腿不挂。同 turn_end 的处置:
|
|
12872
13234
|
# 本地可选声明,不 allOf(不把 identity 承诺进契约面)。
|
|
12873
13235
|
eventId: { type: string }
|
|
12874
13236
|
parentToolCallId: { type: string }
|
|
12875
13237
|
sourceTaskId: { type: string }
|
|
12876
13238
|
bgAgentId: { type: string }
|
|
13239
|
+
ContextUsageSection:
|
|
13240
|
+
# sdk 9.5.0:具名而非内联 —— 与 `WiringManifestMcpEntry` 同一条裁定(一份行形,多处引用)。
|
|
13241
|
+
type: object
|
|
13242
|
+
description: >
|
|
13243
|
+
One rendered section of this leg's SYSTEM PROMPT (core 7.18.0 #790). `id` shares ONE vocabulary with
|
|
13244
|
+
`prompt.assembled`'s `sections[].id`, so the two faces join. See `Event_context_usage.sections` for the
|
|
13245
|
+
do-not-subtract rule — it is the load-bearing half of this shape's contract.
|
|
13246
|
+
additionalProperties: false
|
|
13247
|
+
required: [id, tokens]
|
|
13248
|
+
properties:
|
|
13249
|
+
id: { type: string, description: "The section id — same vocabulary as `prompt.assembled`'s `sections[].id`." }
|
|
13250
|
+
tokens: { type: integer, description: 'PREPARE-time estimate of this section, in ITS OWN coordinate system (see the parent key).' }
|
|
13251
|
+
kind: { type: string, description: 'The semantic slot; ABSENT when the manifest entry declared none (not "no semantics").' }
|
|
12877
13252
|
Event_compaction_outcome:
|
|
12878
13253
|
type: object
|
|
12879
13254
|
description: >
|
|
@@ -13776,6 +14151,66 @@ components:
|
|
|
13776
14151
|
properties:
|
|
13777
14152
|
armed: { type: boolean }
|
|
13778
14153
|
reason: { type: string }
|
|
14154
|
+
hooks:
|
|
14155
|
+
type: array
|
|
14156
|
+
description: >
|
|
14157
|
+
core 7.18.0 (#789), server >= 7.78.0 — the hook seats THIS leg wired, one row per family.
|
|
14158
|
+
EFFECTIVE half only (the diagnostics endpoint's static half never carries it). Present iff at least
|
|
14159
|
+
one seat is wired; absence means "no hook RECORD of this leg", never "no hook runs".
|
|
14160
|
+
Full per-key contract: see Event_wiring_manifest.hooks.
|
|
14161
|
+
items: { $ref: '#/components/schemas/WiringManifestHookEntry' }
|
|
14162
|
+
lsp:
|
|
14163
|
+
allOf: [{ $ref: '#/components/schemas/WiringManifestLspSeam' }]
|
|
14164
|
+
description: >
|
|
14165
|
+
core 7.18.0 (#789), server >= 7.78.0 — the LSP seam. EFFECTIVE half only; present iff a manager
|
|
14166
|
+
seat resolved. `mounted` and `lane` are INDEPENDENT facts — never fold them into one.
|
|
14167
|
+
Full per-key contract: see Event_wiring_manifest.lsp.
|
|
14168
|
+
WiringManifestHookEntry:
|
|
14169
|
+
# sdk 9.5.0:与 `WiringManifestMcpEntry` 同一条裁定 —— 同一份行形被 live 帧与静态诊断面两处引用,
|
|
14170
|
+
# 内联就是两份会各自漂的镜像,所以一开始就具名。
|
|
14171
|
+
type: object
|
|
14172
|
+
description: >
|
|
14173
|
+
One row of a leg's HOOK seat manifest (core 7.18.0 #789): which family, where the seat came from, and
|
|
14174
|
+
whether the `preToolUse` row was DECLARED observational.
|
|
14175
|
+
additionalProperties: false
|
|
14176
|
+
required: [family, owner]
|
|
14177
|
+
properties:
|
|
14178
|
+
family:
|
|
14179
|
+
type: string
|
|
14180
|
+
description: >
|
|
14181
|
+
The hook family. core's closed vocabulary today (`preToolUse` / `postToolUse` / `userPromptSubmit` /
|
|
14182
|
+
`stop` / `postToolUseFailure` / `postToolBatch` / `preCompact` / `postCompact` / `stopFailure` /
|
|
14183
|
+
`permissionDenied`) but READ AS OPEN: the server passes it through verbatim and does not enumerate,
|
|
14184
|
+
so a newly minted family must pass through your default arm.
|
|
14185
|
+
owner:
|
|
14186
|
+
type: string
|
|
14187
|
+
description: "Where the seat came from — core's `SeamProvenance` (`spec` / `deps`). Closed today, read as open."
|
|
14188
|
+
observational:
|
|
14189
|
+
type: boolean
|
|
14190
|
+
enum: [true]
|
|
14191
|
+
description: >
|
|
14192
|
+
Only on the `preToolUse` row, and only when the deployment DECLARED the face observational: it still
|
|
14193
|
+
runs on every call but is not folded into a delegated child's inherited constraints.
|
|
14194
|
+
🔴 NEVER-FALSE — core's words: "Absence means 'not declared', never 'declared false'".
|
|
14195
|
+
WiringManifestLspSeam:
|
|
14196
|
+
# sdk 9.5.0:同上 —— live 帧与静态面共用一份段形。
|
|
14197
|
+
type: object
|
|
14198
|
+
description: >
|
|
14199
|
+
A leg's LSP code-intelligence seam (core 7.18.0 #789). 🔴 THE TWO BITS ARE INDEPENDENT AND MUST NOT BE
|
|
14200
|
+
READ AS ONE: `mounted` is the ROSTER fact (a wired manager whose `LSP` tool was excluded reports
|
|
14201
|
+
`false`), while `lane` arms on the manager / the hands / the opt-out and NOT on the mount — so
|
|
14202
|
+
`{mounted: false, lane: "diagnostics"}` is a REAL, REACHABLE state, not bad data.
|
|
14203
|
+
additionalProperties: false
|
|
14204
|
+
required: [mounted]
|
|
14205
|
+
properties:
|
|
14206
|
+
mounted:
|
|
14207
|
+
type: boolean
|
|
14208
|
+
description: 'Is the LSP tool on this leg''s roster. Required — when the server cannot read it the WHOLE section is absent (it never mints a false).'
|
|
14209
|
+
lane:
|
|
14210
|
+
type: string
|
|
14211
|
+
description: >
|
|
14212
|
+
Which lanes are live — core's closed three (`tool` / `diagnostics` / `tool_and_diagnostics`), read as
|
|
14213
|
+
open. ABSENT = neither lane is live (not "unknown").
|
|
13779
14214
|
WiringManifestMcpEntry:
|
|
13780
14215
|
# 8.9.0:从 `Event_wiring_manifest.mcp.items` 的内联形**提取**为具名 schema —— 同一份行形现在被
|
|
13781
14216
|
# 两处引用(live 帧与 `WiringManifest` 的静态/两半形),内联会立刻变成两份会各自漂的镜像。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/sdk",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.5.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",
|