@sema-agent/sdk 15.2.0 → 15.4.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/openapi.yaml CHANGED
@@ -677,7 +677,8 @@ paths:
677
677
  (non-owner → 404, no existence leak; missing principal → 401). All responses are synchronous ACKs; actual
678
678
  termination is async (same-replica immediate; cross-replica ≈30s via the heartbeat tick). A cancelled run
679
679
  settles to `status` failed + `errorCode` "cancelled" (NO new status — distinguish via errorCode; the UI
680
- shows "cancelled", not an error). A SUSPENDED (or `needs_review`) run IS cancellable here — the server
680
+ shows "cancelled", not an error). From server >= 7.112.0 the cancelled terminal also carries
681
+ `abortCause: "cancel_verb"` (see `TaskResult.abortCause`; `errorCode` "cancelled" is unchanged). A SUSPENDED (or `needs_review`) run IS cancellable here — the server
681
682
  settles its pending checkpoint (CAS `expire`, the reaper's "≈ deny" terminal — deliberately not a
682
683
  resume, since cancel means the run dies) and THEN terminalizes the row, releasing the session claim;
683
684
  the ack is 202. (Corrected 2026-07-31: this paragraph used to say "409 — cancel it by DENYING its
@@ -1057,7 +1058,8 @@ paths:
1057
1058
  responses:
1058
1059
  '200':
1059
1060
  description: >
1060
- Queued/applied. Body `{ taskId, target, status, delivery, marker, note }` — `note` carries the
1061
+ Queued/applied. Body `{ taskId, target, status, delivery, marker, note }` (+ `messageId` from server >= 7.111.0,
1062
+ see `SubagentSteerReceipt`) — `note` carries the
1061
1063
  CC-verbatim "Message queued for delivery to <name> at its next tool round." receipt copy.
1062
1064
  '401': { $ref: '#/components/responses/Unauthorized' }
1063
1065
  '404': { $ref: '#/components/responses/NotFound' }
@@ -1074,6 +1076,18 @@ paths:
1074
1076
  description: 'errorCode "steer.content_too_large" — content over the per-steer cap; shorten and resend (retrying verbatim never succeeds).'
1075
1077
  '429': { $ref: '#/components/responses/RateLimited' } # (declared 2026-07-31) rateLimited||quotaExceeded||leaseDenied all gate this verb (routes/runs.ts)
1076
1078
  '501': { $ref: '#/components/responses/NotImplemented' }
1079
+ '503':
1080
+ description: >-
1081
+ errorCode "steering.ledger_unavailable" (server >=7.111.0, S-966) — a subagent steer enters the same
1082
+ user-input ledger as a run steer (ONE rule: the ledger covers an input whose receipt promised delivery and
1083
+ whose carrying engine stream lives in a run leg of this server), written BEFORE the 200; the ledger could not
1084
+ be written (local data root not writable / SQL unreachable). The subagent received NOTHING. Client action:
1085
+ retry the SAME content later. SDK: `SteeringLedgerUnavailableError`. The sibling `…/resume` verb never
1086
+ takes this arm (a resume starts a new child leg; it does not feed an in-flight queue). Before 7.111.0 this
1087
+ verb wrote no ledger row and never answered 503 for it.
1088
+ content:
1089
+ application/json:
1090
+ schema: { $ref: '#/components/schemas/ErrorResponse' }
1077
1091
 
1078
1092
  /v1/runs/{taskId}/compact:
1079
1093
  parameters:
@@ -7551,7 +7565,8 @@ components:
7551
7565
  `wiring_manifest` frame — test with `'wiringManifest' in result`, never `=== undefined`). The run's
7552
7566
  boot-time wiring receipt: the `wiring_manifest` frame (minted after wiring, before the first turn)
7553
7567
  projected by the SAME projector as the streaming leg (tenant face strips operator-only sections; an
7554
- explicit operator gets the full face). NOT current state — runtime roster changes ride
7568
+ explicit operator gets the full face; server >=7.111.0 carries the self-minted `instructions` section here
7569
+ too, same present-iff reading as `Event_wiring_manifest.instructions`). NOT current state — runtime roster changes ride
7555
7570
  `tool_roster_delta` frames. Shells judge a zero-tool run by `tools.count === 0`.
7556
7571
  terminal:
7557
7572
  allOf: [{ $ref: '#/components/schemas/TerminalCause' }]
@@ -7641,6 +7656,52 @@ components:
7641
7656
  verdict: { type: string, enum: [PASS, FAIL, PARTIAL, unverified] }
7642
7657
  rounds: { type: integer }
7643
7658
  findings: { type: array, items: { type: string } }
7659
+ abortCause:
7660
+ allOf: [{ $ref: '#/components/schemas/AbortCause' }]
7661
+ description: >
7662
+ server >= 7.112.0 (S-947; cli L-212; contract §5.0d; additive) — the machine-readable CAUSE of a SERVER-INITIATED
7663
+ abort, a side key beside `cancelContext` (it is NOT inside `terminal`: `terminal` is the engine's cause, and one
7664
+ object must not have two minters). PRESENT-IFF this result IS the cancelled terminal the server minted for that
7665
+ abort (`terminal.kind: "failed"` + `terminal.code: "cancelled"`); a server >= 7.112.0 always stamps it on the
7666
+ cancelled terminal it mints (the mint's cause parameter is mandatory; the engine never mints `cancelled` itself).
7667
+ 🔴 It sits BESIDE the cancel code and never replaces it: the row's `errorCode` column / `terminal.code`
7668
+ (`"cancelled"`) stays the "this is a cancel" discriminant, unchanged — this key only answers "who made it stop".
7669
+ ABSENT (not a cancelled terminal the server minted for its own abort): a detach disconnect
7670
+ (`x-detach-on-disconnect: true`, the server does not abort); the engine's own failure; a normal completion;
7671
+ `POST /v1/runs/{taskId}/interrupt` (terminal `completed` + `haltedByUser`); a park (including a #241 grace park);
7672
+ a terminal that RACED the abort (the engine finished first / failed with its own code — "fill the empty seat
7673
+ only": code, snapshot and cause are all left off together); a resume leg cancelled BEFORE its approved action
7674
+ started (the engine rules `resume.reopened_unstarted` and the park reopens — the run was not ended); a
7675
+ preempt (`paused`); an orderly shutdown or a dead-holder reap.
7676
+ 🔴 A cancelled row persisted by a server before 7.112.0 has NO `abortCause` and is never back-filled: a row with
7677
+ `errorCode: "cancelled"` and the key absent = cause NOT RECORDED — do not fold it into any word.
7678
+ Four landings, one value: `GET /v1/runs/{taskId}` -> `result.abortCause` (beside `result.cancelContext`) ·
7679
+ `POST /v1/tasks/stream` -> `done.result.abortCause` · the `POST /v1/tasks` 200 body, at its TOP LEVEL (the body IS
7680
+ the result, contract §5.0c) · `GET /v1/runs/{taskId}/events` -> the `done` row's `result.abortCause`; a cancelled
7681
+ shape with NO `done` row to land on (a disconnect after which no done was read / the leg aborted before its
7682
+ terminal threw) lands on the `failed` row at its TOP LEVEL instead (`Event_failed.abortCause`, beside `errorCode`).
7683
+ Two wire VALUE changes ride the same release (not new keys): a resume leg cancelled AFTER the approved action
7684
+ started now ends `failed` + `errorCode: "cancelled"` + a `cancelContext` snapshot + `abortCause: "cancel_verb"`
7685
+ (before 7.112.0 it ended `failed` with NO code); an interactive `POST /v1/tasks/stream` that read no `done` and
7686
+ was NOT aborted by the server now ends with the honest failure sentence `stream ended before a terminal event`
7687
+ (no code, no `abortCause`; before 7.112.0 it was always minted as a "client disconnected" cancelled terminal).
7688
+
7689
+ AbortCause:
7690
+ type: string
7691
+ enum: [client_disconnected, ask_park_grace_exhausted, cancel_verb]
7692
+ description: >
7693
+ The closed three-word vocabulary of `abortCause` (server >= 7.112.0 / S-947; contract §5.0d) — who initiated a
7694
+ server-side abort. Each word has one real site: `client_disconnected` — a non-detach `POST /v1/tasks/stream` client
7695
+ disconnect while no in-stream ask was pending, aborted at once ("the connection dropped, the run was aborted" — not an
7696
+ engine error); `ask_park_grace_exhausted` — the same disconnect arm but an in-stream ask WAS pending: the server first
7697
+ turns the ask into a park through the window-expiry path and gives the engine a bounded grace (10 s) to finish
7698
+ parking, and the park still had not landed when the grace ran out, so the run was aborted; `cancel_verb` —
7699
+ `POST /v1/runs/{taskId}/cancel` (the same-replica fast path, a cross-replica durable cancel flag polled by the holding
7700
+ replica on any of the four legs — interactive stream / non-streaming / background / resume —, and a parked run the
7701
+ verb finalizes directly; the cause is the same word). First come, first served: a leg is aborted once, and the first
7702
+ landing names the word — a cancel verb arriving after a disconnect, or a disconnect after a cancel, never rewrites it.
7703
+ CLOSED set, additive-only by the server's rule (a new word is a new server version in `wire-changes` AND a new SDK
7704
+ minor, in this enum in the same batch): read an unknown word as "the server aborted this run, cause not recognised".
7644
7705
 
7645
7706
  LegacyPlaneTaskResult:
7646
7707
  type: object
@@ -12223,7 +12284,9 @@ components:
12223
12284
  the server had answered 200 `applied` (interrupt{text}: 202) but the process carrying that run died
12224
12285
  before the run settled; whether the run consumed them is NOT known (see `engine_notice`
12225
12286
  `task.user_steer_undrained{cause:"crashed"}`). Converged rows only, one row per (taskId, messageId),
12226
- newest 500. ABSENT = this read has nothing to report (zero rows, or the ledger could not be read —
12287
+ newest 500. From server >=7.111.0 (S-966) the rows include SUBAGENT steers (recorded under the run on the
12288
+ receipt; same row shape, `kind` is still only `steer`; `messageId` = the subagent steer receipt's).
12289
+ ABSENT = this read has nothing to report (zero rows, or the ledger could not be read —
12227
12290
  the authoritative notice is the frame on the run stream); the `?message=` single-entry form never
12228
12291
  carries it.
12229
12292
  items:
@@ -14348,6 +14411,23 @@ components:
14348
14411
  (`capabilities.rewindFiles`); only a run the REQUEST word turned off cannot restore itself.
14349
14412
  OPEN on read: the server does not enumerate the word (a present non-string is dropped), a third word passes
14350
14413
  through — treat it as unknown. ABSENT = an older engine / external derivation, never "capturing".
14414
+ instructions:
14415
+ allOf: [{ $ref: '#/components/schemas/WiringManifestInstructions' }]
14416
+ description: >
14417
+ server >= 7.111.0 (S-961; cli L-910; contract appendix G.21b) — SELF-MINTED by the server (core's
14418
+ `WiringManifest` has no such section; the server adds it beside core's own, and a core section of the
14419
+ same name would be a compile error server-side). TENANT and OPERATOR faces alike; rides the live frame, the
14420
+ durable ledger row and the sync receipt's `wiringManifest`. Which PROJECT-INSTRUCTION FILE the project-memory
14421
+ loader selected on THIS leg's own prepare: the chain `CLAUDE.md` > `.claude/CLAUDE.md` > `AGENTS.md` >
14422
+ `.claude/AGENTS.md` (first hit wins; a present-but-EMPTY `CLAUDE.md` is still the selected one and shadows
14423
+ `AGENTS.md`), each member spelled as the chain spells it, relative to the cwd.
14424
+ 🔴 TWO MEANINGS, never fold them: the key ABSENT = this leg makes NO statement about instruction files
14425
+ (no loader wired — `PROJECT_MEMORY_ENABLED=false`, or the multi-user `REQUIRE_PRINCIPAL=true` form —, a
14426
+ hand-less leg, a cwd that is not a local absolute directory, a delegated subagent leg, or a server older
14427
+ than 7.111.0) — it does NOT mean "there is no instruction file". PRESENT with `selected: []` = the leg
14428
+ walked the chain and selected nothing. Today at most one member is sent (first hit wins); read it as a list.
14429
+ The segment reports what the model read at this leg's prepare, not the disk now (a resume leg reports the
14430
+ session snapshot). Not on `GET /v1/diagnostics/wiring` (a per-leg fact; the static half never mints it).
14351
14431
  eventId: { type: string }
14352
14432
  parentToolCallId: { type: string }
14353
14433
  sourceTaskId: { type: string }
@@ -16601,6 +16681,8 @@ components:
16601
16681
  type: object
16602
16682
  # 封闭 + 回填 `activeTaskId`(census 轴一,2026-07-30):[1833] G10 —— session 已有活跃 run 的冲突
16603
16683
  # 失败形会带上占用者 taskId(SDK events.ts 早已声明,spec 侧漏)。
16684
+ # server 7.112.0(S-947;sdk 15.4.0 / K-42):+`abortCause`(没有 done 可落的取消形的成因落在本行顶层)。封闭对象不声明它,server 的真 `failed` 行对 15.3.0 spec 就是
16685
+ # 「$ must NOT have additional properties」—— 门 6 契约套抓不到这一件,由 `test/server-7112-wire.test.ts` P2(真 `buildCancelledLedgerRow` × spec)抓。
16604
16686
  additionalProperties: false
16605
16687
  required: [type]
16606
16688
  properties:
@@ -16608,6 +16690,16 @@ components:
16608
16690
  errorCode: { type: string }
16609
16691
  errorMessage: { type: string }
16610
16692
  activeTaskId: { type: string, description: '冲突失败形:当前占着该 session 的 run —— 消费方可直接引导 cancel/attach。' }
16693
+ abortCause:
16694
+ allOf: [{ $ref: '#/components/schemas/AbortCause' }]
16695
+ description: >
16696
+ server >= 7.112.0 (S-947; contract §5.0d) — the cause of a cancelled shape that has NO `done` row to carry
16697
+ `result.abortCause` (a disconnect after which no done was read / the leg was aborted before its terminal threw),
16698
+ landing at this row's TOP LEVEL beside `errorCode` (the cancelled shape's `errorCode` is `"cancelled"`, unchanged).
16699
+ Same closed words and the same present-iff gate as `TaskResult.abortCause`: PRESENT-IFF this row is the cancelled
16700
+ shape the server minted for its own abort. A `failed` row WITHOUT `errorCode` / `abortCause` (only
16701
+ `errorMessage`, e.g. `stream ended before a terminal event`) is an honest failure and is NOT a cancel — never
16702
+ read it as "disconnected". A cancelled row persisted before 7.112.0 has no `abortCause` (cause not recorded).
16611
16703
 
16612
16704
  # ══════════════════════════════════════════════════════════════════════════════════════════════
16613
16705
  # 🔴 census 轴一(2026-07-30)补的**四个未登记臂**。它们不是「将来会有」——**今天就在 wire 上**:
@@ -17470,7 +17562,7 @@ components:
17470
17562
  🔴 ONE RULE FOR EVERY "EFFECTIVE HALF ONLY" KEY (sdk 9.7.0, after a codex adversarial-review [high]):
17471
17563
  this schema's only consumer today is `GET /v1/diagnostics/wiring`'s `static` half, and every key marked
17472
17564
  "effective half only" (`leg`, `ask.effective`, `configFingerprint`, `tools`, `hooks`, `lsp`,
17473
- `modelGate`, `autoMode`, `writeProtection`, `readDeny`, `autoConsolidation`, `fileHistory`) is ALWAYS ABSENT on that
17565
+ `modelGate`, `autoMode`, `writeProtection`, `readDeny`, `autoConsolidation`, `fileHistory`, `instructions`) is ALWAYS ABSENT on that
17474
17566
  wire ⇒ THEIR ABSENCE HERE CARRIES NO INFORMATION. The per-key absence readings ("absent = not armed",
17475
17567
  "absent = a third state", …) hold for the LIVE FRAME (`Event_wiring_manifest`) and must not be carried
17476
17568
  over to this response. For the facts behind those keys: a tenant reads
@@ -17651,6 +17743,13 @@ components:
17651
17743
  K-24 (server >= 7.104.0 / S-724) — does this leg capture file history (`on` / `disabled`, OPEN word). EFFECTIVE
17652
17744
  HALF ONLY ⇒ ALWAYS ABSENT ON THIS ENDPOINT; the deployment-level reading is `capabilities.fileHistoryCapture`.
17653
17745
  Full per-key contract: see Event_wiring_manifest.fileHistory.
17746
+ instructions:
17747
+ allOf: [{ $ref: '#/components/schemas/WiringManifestInstructions' }]
17748
+ description: >
17749
+ server >= 7.111.0 (S-961) — SELF-MINTED by the server, PER-LEG: the instruction file the loader selected on one leg's
17750
+ own prepare. EFFECTIVE HALF ONLY ⇒ ALWAYS ABSENT ON THIS ENDPOINT (a deployment has no per-leg selection to report).
17751
+ 🔴 DO NOT read absence here as "no instruction file" — it carries no information on this wire. Full per-key
17752
+ contract: see Event_wiring_manifest.instructions.
17654
17753
  WiringManifestWriteProtection:
17655
17754
  # sdk 9.7.0:与 `WiringManifestMcpEntry` / `WiringManifestLspSeam` 同一条裁定 —— 同一段形被 live 帧与
17656
17755
  # 静态诊断面两处引用,内联就是两份会各自漂的镜像,所以具名单源。
@@ -17698,6 +17797,23 @@ components:
17698
17797
  enum: [true]
17699
17798
  description: "core's ONLY present shape — the construct gate refuses an armed-but-unrunnable state, so this is a SHAPE, not a value."
17700
17799
 
17800
+ WiringManifestInstructions:
17801
+ # S-961(server 7.111.0):与 `WiringManifestReadDeny` / `WiringManifestAutoConsolidation` 同一条裁定 —— 同一段形被 live 帧与静态诊断面两处引用,
17802
+ # 内联就是两份会各自漂的镜像,所以具名单源(`spec-field-drift-gate` 也按「导出的 interface 必有同名 schema」逼出它)。
17803
+ type: object
17804
+ additionalProperties: false
17805
+ description: >
17806
+ The `wiring_manifest.instructions` section (server >= 7.111.0 / S-961) — SELF-MINTED by the server, not a core
17807
+ section: which project-instruction file the project-memory loader selected on this leg's own prepare.
17808
+ `selected` members are a CLOSED four-word set — the server's instruction-file chain (`INSTRUCTION_FILE_CHAIN`,
17809
+ registered in its self-minted wire table `wiringInstructionsSelected`); a fifth chain member would be a new SDK minor,
17810
+ in this enum in the same batch. The present-iff / two-meanings reading is on `Event_wiring_manifest.instructions`.
17811
+ required: [selected]
17812
+ properties:
17813
+ selected:
17814
+ type: array
17815
+ description: 'The selected chain member(s), spelled as the chain spells them (relative to the cwd); `[]` = the chain was walked, nothing was selected.'
17816
+ items: { type: string, enum: ['CLAUDE.md', '.claude/CLAUDE.md', 'AGENTS.md', '.claude/AGENTS.md'] }
17701
17817
  WiringManifestHookEntry:
17702
17818
  # sdk 9.5.0:与 `WiringManifestMcpEntry` 同一条裁定 —— 同一份行形被 live 帧与静态诊断面两处引用,
17703
17819
  # 内联就是两份会各自漂的镜像,所以一开始就具名。
@@ -18011,6 +18127,14 @@ components:
18011
18127
  delivery: { type: string, description: 'Literal "applied" on today''s server.' }
18012
18128
  note: { type: string, description: 'The CC-verbatim queued copy ("Message queued for delivery to <name>…").' }
18013
18129
  marker: { type: string, description: 'Engine-minted delivery marker (present on both steer and resume 200s, server 1.214+).' }
18130
+ messageId:
18131
+ type: string
18132
+ description: >
18133
+ server >= 7.111.0 (S-966) — the STEER 200 only (absent on the `…/resume` 200 and on an older server): the id of
18134
+ this acceptance in the server's user-input ledger (uuidv7) — the SAME value a later
18135
+ `GET /v1/sessions/{id}` `userInputUndrained[].messageId` carries should the carrying server process die
18136
+ before the run settles. The same ledger write that guards a run steer guards a subagent steer: when it
18137
+ cannot be written the verb answers 503 `steering.ledger_unavailable` and the subagent got nothing.
18014
18138
 
18015
18139
  SubagentOutputResult:
18016
18140
  type: object
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/sdk",
3
- "version": "15.2.0",
3
+ "version": "15.4.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",