@sema-agent/sdk 26.1.0 β†’ 27.0.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.
Files changed (78) hide show
  1. package/README.md +81 -1
  2. package/dist/abort.d.ts +25 -0
  3. package/dist/abort.d.ts.map +1 -0
  4. package/dist/abort.js +42 -0
  5. package/dist/abort.js.map +1 -0
  6. package/dist/client.d.ts +8 -3
  7. package/dist/client.d.ts.map +1 -1
  8. package/dist/client.js +5 -4
  9. package/dist/client.js.map +1 -1
  10. package/dist/control-client.d.ts +4 -2
  11. package/dist/control-client.d.ts.map +1 -1
  12. package/dist/control-client.js +3 -3
  13. package/dist/control-client.js.map +1 -1
  14. package/dist/errors.d.ts +32 -10
  15. package/dist/errors.d.ts.map +1 -1
  16. package/dist/errors.js +15 -6
  17. package/dist/errors.js.map +1 -1
  18. package/dist/events.d.ts +3 -0
  19. package/dist/events.d.ts.map +1 -1
  20. package/dist/events.js.map +1 -1
  21. package/dist/model-route-env/index.d.ts +11 -4
  22. package/dist/model-route-env/index.d.ts.map +1 -1
  23. package/dist/model-route-env/index.js +52 -3
  24. package/dist/model-route-env/index.js.map +1 -1
  25. package/dist/registry/auth.d.ts.map +1 -1
  26. package/dist/registry/auth.js +23 -13
  27. package/dist/registry/auth.js.map +1 -1
  28. package/dist/registry/client.d.ts +9 -1
  29. package/dist/registry/client.d.ts.map +1 -1
  30. package/dist/registry/client.js +17 -2
  31. package/dist/registry/client.js.map +1 -1
  32. package/dist/registry/read-body.d.ts +2 -0
  33. package/dist/registry/read-body.d.ts.map +1 -0
  34. package/dist/registry/read-body.js +24 -0
  35. package/dist/registry/read-body.js.map +1 -0
  36. package/dist/registry/scopes-effective.d.ts.map +1 -1
  37. package/dist/registry/scopes-effective.js +4 -2
  38. package/dist/registry/scopes-effective.js.map +1 -1
  39. package/dist/resources/approvals.d.ts +23 -8
  40. package/dist/resources/approvals.d.ts.map +1 -1
  41. package/dist/resources/approvals.js +4 -3
  42. package/dist/resources/approvals.js.map +1 -1
  43. package/dist/resources/attachments.d.ts +2 -1
  44. package/dist/resources/attachments.d.ts.map +1 -1
  45. package/dist/resources/attachments.js +3 -9
  46. package/dist/resources/attachments.js.map +1 -1
  47. package/dist/resources/fleet.d.ts +0 -36
  48. package/dist/resources/fleet.d.ts.map +1 -1
  49. package/dist/resources/fleet.js +40 -1
  50. package/dist/resources/fleet.js.map +1 -1
  51. package/dist/resources/ops.d.ts +2 -1
  52. package/dist/resources/ops.d.ts.map +1 -1
  53. package/dist/resources/ops.js +4 -6
  54. package/dist/resources/ops.js.map +1 -1
  55. package/dist/resources/session-sync.d.ts +11 -3
  56. package/dist/resources/session-sync.d.ts.map +1 -1
  57. package/dist/resources/session-sync.js +7 -8
  58. package/dist/resources/session-sync.js.map +1 -1
  59. package/dist/resources/sessions.d.ts +9 -3
  60. package/dist/resources/sessions.d.ts.map +1 -1
  61. package/dist/resources/sessions.js +10 -12
  62. package/dist/resources/sessions.js.map +1 -1
  63. package/dist/resources/tool-approvals.d.ts +14 -5
  64. package/dist/resources/tool-approvals.d.ts.map +1 -1
  65. package/dist/resources/tool-approvals.js +14 -6
  66. package/dist/resources/tool-approvals.js.map +1 -1
  67. package/dist/sse.d.ts.map +1 -1
  68. package/dist/sse.js +4 -4
  69. package/dist/sse.js.map +1 -1
  70. package/dist/transport.d.ts +61 -21
  71. package/dist/transport.d.ts.map +1 -1
  72. package/dist/transport.js +123 -25
  73. package/dist/transport.js.map +1 -1
  74. package/dist/types.d.ts +30 -8
  75. package/dist/types.d.ts.map +1 -1
  76. package/dist/types.js.map +1 -1
  77. package/openapi.yaml +88 -26
  78. package/package.json +2 -2
package/openapi.yaml CHANGED
@@ -2929,6 +2929,7 @@ paths:
2929
2929
  server >= 7.135.0: `503 state.file_history_unreadable` β€” this session's file history cannot be read WHOLE (a boundary torn / unreadable, the tracked set unreadable); nothing is exported this time. πŸ”΄ It is NOT "no history":
2930
2930
  with nothing to export the manifest still answers `200` with `fileHistory: null`. May carry `permanence` (`transient` / `terminal`; absent = the store did not judge β€” see `ErrorResponse.permanence`). Older servers read an
2931
2931
  unreadable history as "none" (manifest 200 / blob 404).
2932
+ Server >= 7.136.0: the SAME code with `permanence: "transient"` also answers a database / store connection failure on this leg (the entry-id set, policy, anchors, session row, the history read β€” the code's `file_history` is its origin; the action reads `permanence`); before 7.136.0 that fell to a generic `500 internal.error`. The SDK retries this 503 up to `maxRetries` times BEFORE the first byte (the same retrier on all three pull legs), except `permanence: "terminal"` (the store judged retrying useless until it is repaired).
2932
2933
  content:
2933
2934
  application/json:
2934
2935
  schema: { $ref: '#/components/schemas/ErrorResponse' }
@@ -2969,6 +2970,13 @@ paths:
2969
2970
  '401': { $ref: '#/components/responses/Unauthorized' }
2970
2971
  '404': { $ref: '#/components/responses/NotFound' }
2971
2972
  '501': { $ref: '#/components/responses/NotImplemented' }
2973
+ '503':
2974
+ description: >-
2975
+ server >= 7.136.0: `503 state.file_history_unreadable` + `permanence: "transient"` β€” a database / store connection failure BEFORE the response head is sent (nothing is streamed; before 7.136.0 a generic `500 internal.error`). The code's `file_history` is its origin; the action reads `permanence` (see `ErrorResponse.permanence`).
2976
+ A disconnect AFTER the 200 head can only truncate the stream β€” no `{"__sync":"end"}` trailer β€” and is never a 5xx. The SDK retries the 503 up to `maxRetries` times BEFORE the first byte (the same retrier on all three pull legs), except `permanence: "terminal"` (the store judged retrying useless until it is repaired); a truncated body is not retried (resume with `afterSeq`).
2977
+ content:
2978
+ application/json:
2979
+ schema: { $ref: '#/components/schemas/ErrorResponse' }
2972
2980
 
2973
2981
  /v1/sessions/{sessionId}/sync/history/blobs/{hash}:
2974
2982
  parameters:
@@ -3011,6 +3019,7 @@ paths:
3011
3019
  server >= 7.135.0: `503 state.file_history_unreadable` β€” the history cannot be read WHOLE, so the server cannot tell whether this hash is one the session references β€” it does NOT answer "no such blob" (that is `404 not_found.blob`) and gives no bytes. πŸ”΄ It is NOT "no history":
3012
3020
  with nothing to export the manifest still answers `200` with `fileHistory: null`. May carry `permanence` (`transient` / `terminal`; absent = the store did not judge β€” see `ErrorResponse.permanence`). Older servers read an
3013
3021
  unreadable history as "none" (manifest 200 / blob 404).
3022
+ Server >= 7.136.0: the SAME code with `permanence: "transient"` also answers a database / store connection failure on this leg (the history read or the blob bytes read β€” the code's `file_history` is its origin; the action reads `permanence`); before 7.136.0 that fell to a generic `500 internal.error`. The SDK retries this 503 up to `maxRetries` times BEFORE the first byte (the same retrier on all three pull legs), except `permanence: "terminal"` (the store judged retrying useless until it is repaired).
3014
3023
  content:
3015
3024
  application/json:
3016
3025
  schema: { $ref: '#/components/schemas/ErrorResponse' }
@@ -3375,7 +3384,10 @@ paths:
3375
3384
  schema: { $ref: '#/components/schemas/ApprovalDecision' }
3376
3385
  responses:
3377
3386
  '200':
3378
- description: Decision accepted; the run resumes.
3387
+ description: >-
3388
+ Decision accepted. Usually the run (or the parked background agent) resumes; on the two parked-agent forms that can never revive,
3389
+ a DENY (server >= 7.136.0) is answered `{ taskId, status: "failed", decision: "deny" }` instead β€” the card is voided and nothing resumes
3390
+ (see `ParkedDecideAccepted`, `ApprovalDecisionResult`).
3379
3391
  content:
3380
3392
  application/json:
3381
3393
  schema: { $ref: '#/components/schemas/ApprovalDecisionResult' }
@@ -3550,6 +3562,10 @@ paths:
3550
3562
  the claim and rolls back when it is gone or different) β€” a 7.104.0 session delete retires such cards, so this form
3551
3563
  mostly meets cards left by a pre-7.104.0 delete; `decide.row_unrevivable` (DecideError) now also answers when the
3552
3564
  parked row carries no root-session anchor (refused before the claim, nothing consumed).
3565
+ server >= 7.136.0 β€” those two never-revive forms (a parked child whose row carries no agent name; a row with no root-session anchor) keep answering APPROVE with this 409 (the sentence now ends
3566
+ by pointing at deny), but DENY answers `200 { taskId, status: "failed", decision: "deny" }`: the card is voided under its own scope CAS and leaves the pending queue and the
3567
+ `/v1/approvals/stream` snapshot, the child ends `failed`, the gated tool never runs, no `remember` is granted; a lost void CAS is the existing 409 `decide.gate_moved`. Branch on
3568
+ `status` / `errorCode`, not on the sentence.
3553
3569
  content:
3554
3570
  application/json:
3555
3571
  schema: { $ref: '#/components/schemas/ResumeLegConflictError' }
@@ -7375,10 +7391,16 @@ components:
7375
7391
  `egress:true` + `effect:"write"` (core's ruling); `toolAxes` is the caller's explicit override face.
7376
7392
  πŸ”΄ A malformed entry drops the WHOLE peer (named in a warn), never "drop the bad key and keep the
7377
7393
  peer": `allowSkills` is a NARROWING field whose absence means "no restriction", so a half-applied
7378
- entry would turn a narrowing intent into a widening. The request itself is not rejected.
7379
- The center/config baseline wins on a name clash (the peer name IS the tool namespace segment). Over
7380
- the 32-entry cap the surplus entries are DROPPED and named too β€” same disposition as a malformed
7381
- entry, not a 400.
7394
+ entry would turn a narrowing intent into a widening.
7395
+ πŸ”΄ server >= 7.136.0 β€” on a FRESH submit (the three submit doors) a badly written declaration is REFUSED, not dropped, and no longer answers a 200
7396
+ that reads as "in effect": a list that is not an array / an entry that is not an object / a key value the judge cannot read as usable
7397
+ (`url` not an http(s) string, `headers` values that are not strings, `allowSkills` not a string array …) β‡’ `400 request.field_invalid` with the sentence only
7398
+ (no `field` / `reason`); a key outside the peer vocabulary (a mis-spelled `allowSkill` …) β‡’ `400 request.body_shape` + `unknownKeys` (full coordinates, e.g.
7399
+ `a2aPeers[0].allowSkill`); a `url` / `cardUrl` that carries a credential β‡’ `400 request.field_invalid` WITH `field` / `reason` (`url_userinfo` / `url_credential_param`);
7400
+ more than 32 entries β‡’ `400 request.field_invalid` WITH `field: "a2aPeers"` / `reason: "over_cap"` / `count` / `cap`. Branch on `errorCode` / `unknownKeys` / `field`, never on the sentence.
7401
+ The durable-resume REPLAY leg (a stored body re-read on resume) does NOT refuse: it keeps the reader's degradation β€” a bad entry is not mounted and is named in an operator warn, the request is not 400.
7402
+ Servers <= 7.135.x: a malformed entry drops the whole peer (warn), the request is not rejected, and over the cap the surplus is dropped (7.135.0 already answers 400 `over_cap`).
7403
+ The center/config baseline wins on a name clash (the peer name IS the tool namespace segment).
7382
7404
  items: { $ref: '#/components/schemas/A2aServerSpec' }
7383
7405
  resumeAt:
7384
7406
  type: string
@@ -7597,7 +7619,7 @@ components:
7597
7619
  not exceed 5 MiB β€” otherwise the engine refuses BEFORE the first model call (after the UserPromptSubmit hook; not one model token spent) with 400 `config.image_invalid`, whose
7598
7620
  `error` starts with `TaskSpec.images: `. Before 7.117.0 such an image was sent as-is to the model provider and the whole first request failed there (no code to branch on).
7599
7621
  A base64 string longer than 5 242 880 characters (the model API's 5 MB image cap; the server reads the engine's exported constant) is NOT this code: the submit gate refuses it first
7600
- with 413 `request.payload_too_large` (zero model calls, no submit hook, no run row). The `{ url }` arm is unchanged. The model must accept image input (`ModelInfo.vision`; absent = unknown, send anyway).
7622
+ with 413 `request.payload_too_large` (zero model calls, no submit hook, no run row). The `{ url }` arm: from server >= 7.136.0 a URL that carries a credential (`user:pass@host`, or a credential-named query / fragment parameter) is refused on a FRESH submit with 400 `request.field_invalid` + `field: "images[i].url"` + `reason` `url_userinfo` / `url_credential_param` (the sixth seat of the URL-credential judge; send the bytes inline as `{ data, mimeType }` instead β€” an inline image never lands in a URL); the durable-resume replay of a stored body is not judged. Otherwise unchanged (the server has long recognised the type by signature). The model must accept image input (`ModelInfo.vision`; absent = unknown, send anyway).
7601
7623
  items:
7602
7624
  oneOf:
7603
7625
  - type: object
@@ -13299,7 +13321,9 @@ components:
13299
13321
  errorCode?, errorMessage?, retriable?}`, plus `rememberApplied` when the request carried
13300
13322
  `remember:"session"` AND the worker has an exemption store;
13301
13323
  Β· the PARKED-BACKGROUND-AGENT shape (`parked-decide.ts`, server >=1.267) β€” `{taskId, status:"resuming",
13302
- decision}`, an ACCEPTED (not completed) receipt; the revive drives asynchronously.
13324
+ decision}`, an ACCEPTED (not completed) receipt; the revive drives asynchronously. Since server >= 7.136.0 this
13325
+ shape has a SECOND ARM, the VOIDED receipt `{taskId, status:"failed", decision:"deny"}` β€” a DENY on a parked row that can
13326
+ never revive (no agent name / no root-session anchor) voids the card; nothing resumes (see `ParkedDecideAccepted`).
13303
13327
  A FOURTH shape, the #368 IDEMPOTENT REPLAY (server >= 7.4x; declared 2026-09-08 β€” it shipped without
13304
13328
  ever reaching this schema): `{sessionId, idempotent:true, decision, bindingEnforced:true,
13305
13329
  executionOutcome?}` β€” it carries NO `status` and NO `taskId` (nothing was accepted this time). So no key
@@ -13360,7 +13384,7 @@ components:
13360
13384
  description: >
13361
13385
  OPEN string β€” do NOT narrow. Task-level acceptance (server >= 7.37): the literal `resuming` (= accepted,
13362
13386
  resume in flight β€” follow the run stream). Terminal leg: the run's resulting status (`completed`/`failed`/
13363
- `suspended`/`needs_review`). Parked leg: the literal `resuming` (= accepted, revive in flight).
13387
+ `suspended`/`needs_review`). Parked leg: the literal `resuming` (= accepted, revive in flight) β€” or, server >= 7.136.0, the literal `failed` on the VOIDED receipt (a deny that closed a card which could never revive; nothing resumes).
13364
13388
  decision:
13365
13389
  type: string
13366
13390
  enum: [approve, deny]
@@ -13581,7 +13605,14 @@ components:
13581
13605
  description: 'server >= 7.100.0 (S-700): WHY the park row offers no rule β€” the same narrow read and closed set (four words from server >= 7.129.0) as the live card frame and `card_json`.'
13582
13606
  boundGrantAbsence:
13583
13607
  allOf: [{ $ref: '#/components/schemas/BoundGrantAbsence' }]
13584
- description: 'server >= 7.129.0 (core 7.51.0 #1688; park-row fact eight): why this parked card has no grant-binding digest β€” the park-row twin seat `PendingAction.tool_approval.boundGrantAbsence`, the same narrow read and the same name / value as the live frame and the inbox row. ABSENT on this face = a skill card (it carries the digest; the digest itself is not on this face) / a row parked before engine 7.51.0 (says neither β€” the inbox face projects `unreadable` for the same row) / a word outside the set / an old server β€” NOT `not_bindable`.'
13608
+ description: 'server >= 7.129.0 (core 7.51.0 #1688; park-row fact eight): why this parked card has no grant-binding digest β€” the park-row twin seat `PendingAction.tool_approval.boundGrantAbsence`, the same narrow read and the same name / value as the live frame and the inbox row. ABSENT on this face = a skill card (it carries the digest) / a row parked before engine 7.51.0 (says neither β€” the inbox face projects `unreadable` for the same row) / a word outside the set / an old server β€” NOT `not_bindable`.'
13609
+ boundGrantDigest: { type: string, description: 'server >= 7.136.0 β€” a parked `Skill` card''s grant-binding digest; the same value as the inbox row''s and the live frame''s `boundGrantDigest` (one projection feeds this operator queue row, the `/v1/approvals/stream` `pending` frame and the inbox row β€” byte-equal for the same parked row). Present only on a skill card; absent on an ordinary card. `card_json` does not carry it. Server <= 7.135.x: not on this face.' }
13610
+ boundGrants:
13611
+ allOf: [{ $ref: '#/components/schemas/BoundSkillGrants' }]
13612
+ description: 'server >= 7.136.0 β€” the value `boundGrantDigest` hashes, published ONLY when it hashes to it (digest only when they disagree; no digest, no list). DEPLOYMENT TEXT (skill names and list entries are written by the deployer; the server neither redacts nor escapes them): render with contextual escaping.'
13613
+ classifierNoRuling:
13614
+ allOf: [{ $ref: '#/components/schemas/AutoModeFallbackCause' }]
13615
+ description: 'server >= 7.136.0 β€” only on a parked `classifier_no_ruling` card: why the auto-mode classifier did not rule (closed set, echoed only when a member). Same value as the inbox row''s and the live frame''s.'
13585
13616
  askClass:
13586
13617
  allOf: [{ $ref: '#/components/schemas/AskClass' }]
13587
13618
  description: 'server >= 7.109.0 (S-934 β‘‘ / core 7.37.0 #1214): the park-row twin seat `PendingAction.tool_approval.askClass`, read through `readAskClassPair` β€” the SAME narrow read as the live frame and the card. Present together with `classes` (`classes[0] === askClass`); the basis a durable approver answers by. Absent = an old row (parked before core 7.37.0; resume does not backfill) or an unreadable pair β€” NOT "no class". The inbox row (InboxRow) does not carry it.'
@@ -13735,7 +13766,7 @@ components:
13735
13766
  classifierNoRuling:
13736
13767
  allOf: [{ $ref: '#/components/schemas/AutoModeFallbackCause' }]
13737
13768
  description: 'server >= 7.118.0 β€” only on a parked `classifier_no_ruling` card: why the auto-mode classifier did not rule.'
13738
- objective: { type: ['string', 'null'], description: 'task objective, null if unavailable.' }
13769
+ objective: { type: ['string', 'null'], description: 'task objective, null if unavailable. server >= 7.136.0: the run row''s `objectivePreview` (redacted when written, about 120 characters β€” the same column as `GET /v1/assistant/tasks`; looked up through the gate''s session: its active run, else its latest run; a delegated child''s gate β€” whose session has no run of its own β€” falls back to the run that spawned it, via the parked agent row''s `parentTaskId`, hop by hop, at most 8 hops) β€” null when no preview could be read (a deployment without a run ledger is one cause; a failed read of the row, a delegation chain that breaks or exceeds 8 hops, or a run row without a preview also answer null β€” the key does not say which). Before 7.136.0 this was the objective ORIGINAL stored in the parked context (not truncated, not redacted); a consumer that used it as the full objective should know that server 7.136.0 has no full-objective read face (`GET /v1/runs/:id` carries neither `objective` nor `objectivePreview`) β€” this key IS the preview; a full read face comes with a later server version and this package locksteps then (no substitute path is declared here).' }
13739
13770
  input:
13740
13771
  description: >
13741
13772
  REDACTED tool-args preview for display (null on gates without one, e.g. plan_review). Untyped by
@@ -14153,7 +14184,9 @@ components:
14153
14184
  non-object is `400 request.body_shape`. `title`: a string renames (1..120 CHARACTERS counted as Unicode characters = the storage column width, no leading /
14154
14185
  trailing whitespace, stored verbatim β€” not rewritten, not redacted); `null` CLEARS it back to the automatic title (the next submit lets the auto-titler fill
14155
14186
  it again). `""` is NOT a clear β€” it is `400 request.body_shape`. A string of the wrong form / a non-string-non-null `title` / a non-boolean `pinned` is
14156
- `400 request.field_invalid`.
14187
+ `400 request.field_invalid`; from server >= 7.136.0 a title made only of invisible characters (zero-width, bidi controls, soft hyphen, C1 controls β€” empty after the cross-session peer directory's own
14188
+ usable-name normalization) is `400 request.field_invalid` too (`title must contain at least one visible character`; the session-sync 2c import's `title` reads the same rule). Such titles written before
14189
+ 7.136.0 are not migrated.
14157
14190
  additionalProperties: false
14158
14191
  minProperties: 1
14159
14192
  properties:
@@ -15067,8 +15100,8 @@ components:
15067
15100
  type: string
15068
15101
  enum: [transient, terminal]
15069
15102
  description: >-
15070
- server >= 7.135.0, on `503 state.file_history_unreadable` and `422 adopt_failed` only: the file-history store's own judgment of the fault (the engine's `GovernanceRetryClass`) β€”
15071
- `transient` = nothing was changed, retrying the same shape later may succeed; `terminal` = repair the store first. ABSENT = the store did not judge (retry later once; still red β‡’ look at the store). SDK: `err.extra.permanence`.
15103
+ server >= 7.135.0, on `503 state.file_history_unreadable` and the file-history store's fault answers (`422 adopt_failed`; server >= 7.136.0 also `restore_failed` and the like, and the session-sync pull legs' database-disconnect `503`, where `transient` is judged for connection-class faults): the file-history store's own judgment of the fault (the engine's `GovernanceRetryClass`) β€”
15104
+ `transient` = nothing was changed, retrying the same shape later may succeed; `terminal` = repair the store first. ABSENT = the store did not judge; not terminal β€” retried by status like any retryable 5xx (the SDK does so automatically on the pull legs, up to `maxRetries`); still red β‡’ look at the store. SDK: `err.extra.permanence`.
15072
15105
  ordinal:
15073
15106
  type: integer
15074
15107
  description: >-
@@ -15079,7 +15112,7 @@ components:
15079
15112
  A per-code closed word β€” read it by `errorCode`, never across codes. On 400 `request.field_invalid` for a URL that carries a credential (server >= 7.135.0): `url_userinfo` (`user:pass@host`) / `url_credential_param` (a credential-named
15080
15113
  query / fragment parameter β€” the names the service's log redactor treats as credentials), beside `field` = the body coordinate (`mcpServers[i].transport.url`, `a2aPeers[i].url`, `a2aPeers[i].cardUrl`,
15081
15114
  `settings.hooks.<event>[g].hooks[h].url` β€” the FULL coordinate, not `field: "settings.hooks"` + `detail` β€” and `settings.webSearch.endpoint`; a `settings.webSearch.endpoint` with userinfo keeps its sentence and gains `field` / `reason`);
15082
- `a2aPeers` over 32 entries answers `over_cap` + `count` + `cap` on `field: "a2aPeers"`. On 503 `fleet.lease_unavailable` (server >=
15115
+ `a2aPeers` over 32 entries answers `over_cap` + `count` + `cap` on `field: "a2aPeers"`. Server >= 7.136.0: the same URL-credential words on a SIXTH seat, `images[i].url` (`field` = `images[i].url`, an `images` `{ url }` arm β€” fresh submits only); `mcpServers` over 32 entries answers `over_cap` + `count` + `cap` on `field: "mcpServers"` (the same body as `a2aPeers`; the probe door `POST /v1/capabilities/mcp/probe` answers the same sentence and keys β€” before 7.136.0 a sentence without machine keys); a malformed `a2aPeers` list / entry / key value carries NO `reason` (sentence only), a key outside the peer vocabulary is `request.body_shape` + `unknownKeys`. On 503 `fleet.lease_unavailable` (server >=
15083
15116
  7.106.0 / S-866 β‘’): `auth-rejected` (the center refused this engine's credential, or the credential file is
15084
15117
  unreadable) / `unreachable` (unreachable / 5xx / timeout / bad body / any status other than 200 / 409 / 400 / 401 / 403 β€”
15085
15118
  center 404 / 429 / 3xx included). On 400 `request.field_invalid` for a `settings.permissions` bucket (server >= 7.106.0 /
@@ -15117,6 +15150,10 @@ components:
15117
15150
  `[i]`, record members `.key`: `mcpServers[0].transport.headers.Authorization`, `settings.hooks.PreToolUse[0].hooks[0].headers.Authorization`; the key
15118
15151
  name is not a secret, the value never enters the refusal); on 400 `request.field_invalid` for the request key `settings.approvalFrameFamilies` it is
15119
15152
  that literal (with `reason: "bad_entry"` and the bad `index`; no `index` for a non-array).
15153
+ server >= 7.135.0: on 409 `conflict.checkpoint_ctx_unsealable` with `reason: "unrecognized_seal"` the arm of the stored credential-slot GENERATION newer than this server's (or not a positive integer) reads `field: "credentialSlotGeneration"` β€” not an in-body coordinate.
15154
+ server >= 7.136.0: the credential-slot set gains four seats (generation 3) β€” `mcpServers[i].transport.command` / `mcpServers[i].transport.args` (stdio transport) and `settings.hooks.<event>[g].hooks[h].command` / `.args` (command hook); `args` is sealed as ONE value (the whole array); on 409 `conflict.checkpoint_ctx_unsealable` `field` names that coordinate (which doors can answer which `reason`, and how the refusal arrives, is written once β€” in the SDK documentation of `CHECKPOINT_CTX_UNSEALABLE_REASONS` β€” not repeated here).
15155
+ server >= 7.136.0: on 400 `request.field_invalid` for a URL that carries a credential, `field` also names `images[i].url` (the sixth seat); on `mcpServers` over 32 entries `field` is `mcpServers` (beside `reason: "over_cap"` / `count` / `cap`); a key outside the `a2aPeers` entry vocabulary is `400 request.body_shape` whose `unknownKeys` carry the full coordinates (`a2aPeers[0].allowSkill`).
15156
+ server >= 7.135.0: on `a2aPeers` over 32 entries `field` is `a2aPeers` (beside `reason: "over_cap"` / `count` / `cap`).
15120
15157
  detail:
15121
15158
  description: >
15122
15159
  πŸ”΄ SHAPES differ by code β€” branch on `field` (or the `errorCode`), never guess from the type of `detail`. On 503
@@ -18100,7 +18137,7 @@ components:
18100
18137
  second card word `contentKind` that server <= 7.125.x derived from the tool name (deleted at 7.126.0, no alias: a consumer reading `contentKind === "content_ask"` reads
18101
18138
  `approvalCard === "question"`). ABSENT = the engine minted none (a host-built ask / an older engine / a non-approval gate) β€” never `generic` by default. Display / triage only; it NEVER
18102
18139
  takes part in resume / gate / CAS. The same word rides the `livePending` row top level (= this frame's own value), the operator queue row and the `/v1/approvals/stream` `pending` /
18103
- `live_pending` frames; the `card_json` card face and the `approval_request` frame's `card` do NOT carry it (`ApprovalCard` is `.strict()`).
18140
+ `live_pending` frames; from server >= 7.136.0 the `card_json` card face and the `approval_request` frame's `card` (live mint and reconnect replay alike) carry the same word too (`ApprovalCard.approvalCard`: one read, three faces β€” before 7.136.0 the card did not carry it, so a replayed frame had none and a reconnecting shell fell back to the generic card).
18104
18141
  inputHasBidi:
18105
18142
  type: boolean
18106
18143
  enum: [true]
@@ -18379,6 +18416,9 @@ components:
18379
18416
  argsOmitted: { type: boolean, enum: [true], description: 'Present (true) only when args exceeded the byte cap. Never false.' }
18380
18417
  toolCallId: { type: string, description: 'The engine''s tool-call id (the `call_…` on the assistant message''s tool_use block) β€” same domain as ToolApprovalFrame.toolCallId.' }
18381
18418
  risk: { $ref: '#/components/schemas/ApprovalRiskAxes' }
18419
+ approvalCard:
18420
+ allOf: [{ $ref: '#/components/schemas/ToolApprovalCardWord' }]
18421
+ description: 'server >= 7.136.0, ADDITIVE: the engine-minted card word β€” the SAME word, read once, as the live frame''s top-level `ToolApprovalFrame.approvalCard`; it now rides the live-minted `approval_request` frame''s `card`, the stored `card_json` envelope and the reconnect-replay frame''s `card` (before 7.136.0 the card did not carry it, so a replayed frame had none). ABSENT = the engine minted none / an out-of-set word (the server narrows it again when it mints the card) / a card stored before 7.136.0 β€” never `generic` by default. Display / triage only; it NEVER takes part in resume / gate / CAS. The stored envelope is strict: a 7.135.x replica cannot read a row carrying this key (replay skips it, the idempotent re-entry goes to the durable park) β€” roll the fleet in one pass.'
18382
18422
  rememberRefused:
18383
18423
  type: boolean
18384
18424
  enum: [true]
@@ -20212,6 +20252,13 @@ components:
20212
20252
  boundGrantAbsence:
20213
20253
  allOf: [{ $ref: '#/components/schemas/BoundGrantAbsence' }]
20214
20254
  description: '`pending` frames only (server >= 7.129.0 / core 7.51.0 #1688) β€” see PendingCheckpoint.boundGrantAbsence. A `live_pending` frame carries it only inside its `frame`.'
20255
+ boundGrantDigest: { type: string, description: '`pending` frames only (server >= 7.136.0) β€” see PendingCheckpoint.boundGrantDigest. A `live_pending` frame carries it only inside its `frame`.' }
20256
+ boundGrants:
20257
+ allOf: [{ $ref: '#/components/schemas/BoundSkillGrants' }]
20258
+ description: '`pending` frames only (server >= 7.136.0) β€” see PendingCheckpoint.boundGrants. DEPLOYMENT TEXT: render with contextual escaping.'
20259
+ classifierNoRuling:
20260
+ allOf: [{ $ref: '#/components/schemas/AutoModeFallbackCause' }]
20261
+ description: '`pending` frames only (server >= 7.136.0) β€” see PendingCheckpoint.classifierNoRuling.'
20215
20262
  askClass:
20216
20263
  allOf: [{ $ref: '#/components/schemas/AskClass' }]
20217
20264
  description: '`pending` frames only (server >= 7.109.0 / S-934 β‘‘) β€” see PendingCheckpoint.askClass. A `live_pending` frame carries the pair only inside its `frame`.'
@@ -20222,20 +20269,35 @@ components:
20222
20269
  description: '`pending` frames only (server >= 7.109.0) β€” see PendingCheckpoint.classes.'
20223
20270
 
20224
20271
  ParkedDecideAccepted:
20225
- type: object
20226
20272
  description: >
20227
20273
  The 200 body of POST /v1/approvals/{sessionId}/decide when the pending checkpoint belongs to a
20228
20274
  PARKED background agent (server 1.267, ASSISTANT-WIRE-CONTRACT Β§4a parked variant; server
20229
- parked-decide.ts β€” exact literal shape). ACCEPTANCE semantics: the revive drives
20230
- ASYNCHRONOUSLY β€” 200 means accepted, not completed; a failed drive honestly re-parks the row and
20231
- the pending re-appears on the list. Task-level suspends keep the legacy resumed shape β€”
20232
- discriminate by `status === "resuming"`.
20233
- required: [taskId, status, decision]
20234
- additionalProperties: true
20235
- properties:
20236
- taskId: { type: string, description: 'The background agent handle (a* domain).' }
20237
- status: { type: string, enum: [resuming] }
20238
- decision: { type: string, enum: [approve, deny] }
20275
+ parked-decide.ts β€” exact literal shapes). TWO ARMS, read by `status` (the SDK type `ParkedDecideAccepted` is their union):
20276
+ (1) `status: "resuming"` β€” the ACCEPTANCE receipt. The revive drives ASYNCHRONOUSLY β€” 200 means accepted,
20277
+ not completed; a failed drive honestly re-parks the row and the pending re-appears on the list.
20278
+ (2) `status: "failed"` (server >= 7.136.0; `decision` is always `deny`) β€” the VOIDED receipt: on the two forms that can
20279
+ never revive (a parked child whose row carries no agent name β€” an unnamed `Agent` call β€” or no root-session anchor)
20280
+ a DENY voids the card under its own scope CAS; the card leaves the pending queue and the `/v1/approvals/stream` snapshot,
20281
+ the child ends `failed` (the engine's reconcile), the gated tool never runs, no `remember` is granted β€” and NOTHING is
20282
+ resuming. Do not wait for a revive that never comes. APPROVE on those forms stays `409 decide.row_unrevivable`; a lost
20283
+ void CAS is the existing `409 decide.gate_moved`.
20284
+ Task-level suspends answer their own shapes (see `ApprovalDecisionResult`): discriminate a parked receipt by `decision`
20285
+ present and `sessionId` absent, then read `status`.
20286
+ oneOf:
20287
+ - type: object
20288
+ required: [taskId, status, decision]
20289
+ additionalProperties: true
20290
+ properties:
20291
+ taskId: { type: string, description: 'The background agent handle (a* domain).' }
20292
+ status: { type: string, enum: [resuming] }
20293
+ decision: { type: string, enum: [approve, deny] }
20294
+ - type: object
20295
+ required: [taskId, status, decision]
20296
+ additionalProperties: true
20297
+ properties:
20298
+ taskId: { type: string, description: 'The background agent handle (a* domain).' }
20299
+ status: { type: string, enum: [failed] }
20300
+ decision: { type: string, enum: [deny] }
20239
20301
 
20240
20302
  FleetMeta:
20241
20303
  type: object
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/sdk",
3
- "version": "26.1.0",
3
+ "version": "27.0.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",
@@ -55,6 +55,6 @@
55
55
  "prepublishOnly": "rm -f tsconfig.tsbuildinfo && npm run build && npm run typecheck --workspaces=false --prefix ../.. && npm test --workspaces=false --prefix ../.. && npm run prepack"
56
56
  },
57
57
  "devDependencies": {
58
- "@sema-agent/settings-schema": "^14.4.0"
58
+ "@sema-agent/settings-schema": "^14.5.0"
59
59
  }
60
60
  }