@sema-agent/sdk 7.4.0 → 8.1.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 (42) hide show
  1. package/README.md +62 -0
  2. package/dist/errors.d.ts +32 -6
  3. package/dist/errors.d.ts.map +1 -1
  4. package/dist/errors.js +35 -3
  5. package/dist/errors.js.map +1 -1
  6. package/dist/events.d.ts +19 -7
  7. package/dist/events.d.ts.map +1 -1
  8. package/dist/events.js.map +1 -1
  9. package/dist/index.d.ts +6 -4
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/resources/fleet.d.ts +39 -6
  14. package/dist/resources/fleet.d.ts.map +1 -1
  15. package/dist/resources/fleet.js.map +1 -1
  16. package/dist/resources/images.d.ts +5 -1
  17. package/dist/resources/images.d.ts.map +1 -1
  18. package/dist/resources/images.js +11 -7
  19. package/dist/resources/images.js.map +1 -1
  20. package/dist/resources/rules.d.ts +33 -8
  21. package/dist/resources/rules.d.ts.map +1 -1
  22. package/dist/resources/rules.js.map +1 -1
  23. package/dist/resources/runs.d.ts +6 -1
  24. package/dist/resources/runs.d.ts.map +1 -1
  25. package/dist/resources/runs.js +13 -7
  26. package/dist/resources/runs.js.map +1 -1
  27. package/dist/resources/tool-approvals.d.ts +22 -7
  28. package/dist/resources/tool-approvals.d.ts.map +1 -1
  29. package/dist/resources/tool-approvals.js +7 -2
  30. package/dist/resources/tool-approvals.js.map +1 -1
  31. package/dist/resources/trace.d.ts +9 -8
  32. package/dist/resources/trace.d.ts.map +1 -1
  33. package/dist/resources/trace.js +15 -14
  34. package/dist/resources/trace.js.map +1 -1
  35. package/dist/sse.d.ts +25 -2
  36. package/dist/sse.d.ts.map +1 -1
  37. package/dist/sse.js +30 -16
  38. package/dist/sse.js.map +1 -1
  39. package/dist/types.d.ts +20 -0
  40. package/dist/types.d.ts.map +1 -1
  41. package/openapi.yaml +205 -65
  42. package/package.json +1 -1
package/openapi.yaml CHANGED
@@ -2533,7 +2533,11 @@ paths:
2533
2533
  member since core 5.7.0/RB-459: the content-ask `answer` payload was refused) — your binding does
2534
2534
  NOT match the current pending action (TOCTOU/swap). The SDK splits these by `errorCode` into
2535
2535
  ConflictError vs ApprovalBindingMismatchError. binding_mismatch = SAFETY signal: refetch + re-present
2536
- to the human, NEVER auto-retry.
2536
+ to the human, NEVER auto-retry. (S-57, server >= 7.54.0: the `field:"boundCallId"` shape is
2537
+ intercepted in steady state by the `approval_stale` second trigger source below — the server
2538
+ compares the echoed boundCallId against the current pending pre-CAS and answers 409
2539
+ `approval_stale` + `currentPending`; this code's boundCallId arm covers only the remaining race
2540
+ window between that compare and the core CAS. The hash/answer arms are unchanged.)
2537
2541
  FOURTH member ([2400] CB-2, declared 2026-08-02): `gate_not_tool_approval` — the suspension this
2538
2542
  sessionId is parked on is NOT a tool-approval gate (`src/http/server.ts` rejects pre-CAS when the
2539
2543
  gate kind is neither `human` nor `irreversible_ask`: nothing is consumed, no model leg burns). It is
@@ -2541,6 +2545,14 @@ paths:
2541
2545
  `gate_not_plan_review` (§4c) → SDK `GateNotToolApprovalError`. Client action: route by the row's
2542
2546
  `gateKind` — `plan_review` → `POST /v1/assistant/tasks/{taskId}/plan_review`, `resource_limit` →
2543
2547
  `POST /v1/assistant/tasks/{taskId}/resume`. Retrying the same body never succeeds.
2548
+ SIXTH group (A-075.10, TIME-BASED retry-later pair): `resume.usage_window_exhausted` (#449 G1,
2549
+ core 5.60.1 — the deployment governance window on this run's ledger key is full; NOTHING was
2550
+ consumed or unpinned, the SAME token with the SAME decision redeems once the window slides) and
2551
+ `resume.preflight_rejected` (#376, core 5.65 retry-later form). Both are PRE-CAS (the checkpoint
2552
+ stays pending) and their body ADDITIVELY carries `retryAfterSec` (seconds, ceil, min 1; the
2553
+ server mints the key ONLY on these two codes with a finite positive wait) → SDK
2554
+ `ResumeRetryLaterError` (a `SubagentResumeConflictError` subclass so existing family catches
2555
+ keep matching; `.retryAfterSec` is the actionable wait).
2544
2556
  FIFTH group ([2400] CB-2): the core `checkpoint.*` family the server mirrors verbatim
2545
2557
  (`src/http/server.ts`) — `checkpoint.gate_mismatch` / `checkpoint.reopen_failed` /
2546
2558
  `checkpoint.reopen_revote` / `checkpoint.already_exists` / `checkpoint.resume_aborted` /
@@ -2560,11 +2572,15 @@ paths:
2560
2572
  checkpointToken. Absent when there is no pending / the gate is not a tool approval / the row read
2561
2573
  failed (loud fail-open ledger arm) / an older server. Owner domain = the route's owner gate (no
2562
2574
  new disclosure surface). SDK: `ApprovalStaleError.currentPending`, whole-or-absent guard.
2563
- REACHABILITY (codex 复审 R1-[medium] 采纳成文): the stale arm fires only for callers that ECHO a
2564
- `checkpointToken`; this SDK's ApprovalDecision deliberately has no such field (removed in 1.0.0 —
2565
- resume credentials never ride the compliant decide), so decides issued through this SDK never
2566
- trigger it. The key is documented for the wire contract's sake: legacy shells and non-SDK callers
2567
- that still echo tokens DO reach it, and the SDK's read side stays typed for whatever arrives.
2575
+ REACHABILITY (REWRITTEN for S-57, server >= 7.54.0): the stale arm now has TWO trigger sources —
2576
+ (1) a caller echoing a legacy `checkpointToken` (this SDK's ApprovalDecision deliberately has no
2577
+ such field, removed in 1.0.0 — resume credentials never ride the compliant decide), and
2578
+ (2) an echoed `boundCallId` that does not match the session's CURRENT pending row (the COMPLIANT
2579
+ SDK shape — the server compares pre-CAS and answers this 409 + `currentPending` directly; this
2580
+ form never carries `terminal`). So a decide issued through this SDK DOES reach this 409 under
2581
+ coordinate rotation (before S-57 that shape fell through to `approval_binding_mismatch` +
2582
+ `field:"boundCallId"` with no pointer key; that arm now covers only the race window between the
2583
+ server-side compare and the core CAS).
2568
2584
  ALSO an S-02 behavior NARROWING on this arm: an echoed `checkpointToken` that does NOT belong to
2569
2585
  this session, when the session has NO pending, now folds into the byte-identical 404
2570
2586
  `not_found.approval` (it used to 409 — a single-bit cross-tenant "who is parked on an approval"
@@ -5764,15 +5780,42 @@ components:
5764
5780
  Run state (`GET /v1/runs/:id`) — live shape per the pinned wire contract Drift 2: `result` is the NESTED TaskResult
5765
5781
  object (output text in result.result, stats in result.stats; NO top-level stats), and the error text
5766
5782
  field is `error` (not errorMessage; errorCode is floated up from result.errorCode).
5767
- # 封闭(census 轴一,2026-07-30):铸造点 routes/runs.ts 是一个逐键写死的字面量,恰好 10 键
5768
- # (taskId/sessionId/status/result/supervisorCost/suggestions/errorCode/error/jobId/source),与本
5769
- # properties 一一对上;只有前三键无条件在场(其余走 `?? undefined` ⇒ JSON 丢键)⇒ required 维持 3 键。
5783
+ # 封闭(census 轴一,2026-07-30;A-075.21 回填后 12 键):铸造点 routes/runs.ts 是一个逐键写死的
5784
+ # 字面量(taskId/sessionId/status/msSinceLastActivity/crossSliceUsage/result/supervisorCost/
5785
+ # suggestions/errorCode/error/jobId/source),与本 properties 一一对上;只有 taskId/sessionId/status
5786
+ # 无条件在场(其余走 `?? undefined` / 条件 spread ⇒ JSON 丢键)⇒ required 维持 3 键。
5787
+ # (A-075.21:此前的「恰好 10 键」对 msSinceLastActivity(#245 S1)/crossSliceUsage([3833] S-4)
5788
+ # 两条铸键路径结构性失明 —— server test/producer-contract.test.ts 的 S-4 登记钉逐字记着这笔账。)
5770
5789
  additionalProperties: false
5771
5790
  required: [taskId, sessionId, status]
5772
5791
  properties:
5773
5792
  taskId: { type: string }
5774
5793
  sessionId: { type: string }
5775
5794
  status: { $ref: '#/components/schemas/RunStatus' }
5795
+ msSinceLastActivity:
5796
+ type: integer
5797
+ description: >
5798
+ #245 S1 (server >= 7.18) — ms since the run's last activity (poll-face liveness evidence; same key
5799
+ and semantics as the 409 conflict body). SAME-REPLICA BEST-EFFORT: absent when the poll lands on a
5800
+ replica that never ran this run. Absence = cannot prove, NOT 0/fresh.
5801
+ crossSliceUsage:
5802
+ type: object
5803
+ description: >
5804
+ [3833] S-4 (server >= 7.48.0) — cross-slice governance-window usage, present only on a running
5805
+ (non-stale) row polled on the replica that registered the window. Reading discipline: values are
5806
+ LOWER BOUNDS (ledgered at turn boundaries, delegation subtree excluded); the three axes come in
5807
+ PAIRS (an unconfigured cap omits its pair; spentMicroUsd may also be absent when unpriced — 0
5808
+ would lie); WHOLE-KEY ABSENCE does NOT mean "nothing spent" (no cap / not running / wrong replica
5809
+ / ledger unavailable are indistinguishable); on resumed legs the totals stay frozen on the first
5810
+ slice's ledger, never overwritten by current env.
5811
+ additionalProperties: false
5812
+ properties:
5813
+ totalTokens: { type: integer }
5814
+ spentTokens: { type: integer }
5815
+ totalBudgetMicroUsd: { type: integer, description: 'Integer micro-USD (display divides by 1e6).' }
5816
+ spentMicroUsd: { type: integer, description: 'Integer micro-USD; absent on unpriced deployments (unknown, not 0).' }
5817
+ maxSlices: { type: integer }
5818
+ sliceCount: { type: integer }
5776
5819
  result: { $ref: '#/components/schemas/TaskResult' }
5777
5820
  errorCode:
5778
5821
  type: string
@@ -7271,19 +7314,25 @@ components:
7271
7314
  note: { type: string }
7272
7315
  SessionWakeResult:
7273
7316
  # 4.3.0(SM-9):wake 200 形提成具名 schema(形与下面 /wake 路径的 200 逐字同源)。
7317
+ # A-075.1(车AE,2026-09-01):#354 只修了 inline 路径 200,这只具名形停在旧二键 required、封闭形下
7318
+ # 缺 `bindingEnforced` ⇒「逐字同源」自称为假、严格生成客户端拒收真响应。现与 inline 重新逐字对齐
7319
+ # (spec.test.ts 的 A-075.1 组机器看守同源等式)。
7274
7320
  type: object
7275
7321
  description: >
7276
7322
  POST /v1/sessions/{sessionId}/wake 的 200 形。⚠️ 200 也可能带 `errorCode`(core 侧 `wake.*` 拒了) ——
7277
- 按机器码分支,别只看 HTTP 状态码。
7323
+ 按机器码分支,别只看 HTTP 状态码。ACCEPTANCE form (durable row present, [3833] S-1): status
7324
+ "resuming", the leg keeps running server-side. SYNCHRONOUS form (no durable run row): status is the
7325
+ run's resulting terminal enum. `bindingEnforced` is always true on BOTH forms (both mint points).
7278
7326
  additionalProperties: false
7279
- required: [sessionId, status]
7327
+ required: [sessionId, status, bindingEnforced]
7280
7328
  properties:
7281
- sessionId: { type: string }
7282
- status: { type: string, description: 'The run''s resulting status (core TaskStatus verbatim).' }
7283
7329
  taskId: { type: string, description: 'The active run id; OMITTED when no active row.' }
7284
- errorCode: { type: string, description: 'Failure code when the resumed leg failed / was refused.' }
7285
- errorMessage: { type: string, description: 'Human-readable failure detail (server-side secret-redacted).' }
7286
- retriable: { type: boolean, description: 'true = the park is STILL pending (re-parked); refetch and retry.' }
7330
+ sessionId: { type: string }
7331
+ status: { type: string, description: 'ACCEPTANCE form (durable row present, [3833] S-1): "resuming" — the leg keeps running server-side; follow GET /v1/runs/:id or the events tail for the outcome. SYNCHRONOUS form (no durable run row): the run''s resulting status (completed/failed/suspended/needs_review/blocked — core TaskStatus verbatim; "timeout" retired in core 5.8.0: walltime exhaustion now lands as failed + errorCode limits.max_walltime_exceeded).' }
7332
+ bindingEnforced: { type: boolean, description: '[2400] HITL-12 generation probe — this server enforces decision-action binding. Always true (present on BOTH 200 forms).' }
7333
+ errorCode: { type: string, description: 'Failure code when the resumed leg failed (e.g. `cancelled`). Synchronous form only — never on the acceptance form.' }
7334
+ errorMessage: { type: string, description: 'Human-readable failure detail (server-side secret-redacted). Synchronous form only.' }
7335
+ retriable: { type: boolean, description: 'true = the park is STILL pending (re-parked); refetch and retry. Synchronous form only.' }
7287
7336
  WorkflowJournalRow:
7288
7337
  # 🔴 census 批2 四段:CLOSED against server's real projected/truncated row shapes — a row is EITHER the
7289
7338
  # projected result OR an honest truncated stub(超 64KiB 的行从不进程内存,投影为 truncated stub)。
@@ -7677,27 +7726,29 @@ components:
7677
7726
  parentToolCallId: { type: string, description: 'The parent tool_use id VERBATIM (E2 domain, engine-minted) — [1832] P1-2, server >= 1.290 / engine 1.432; the terminal notification frame carries it too. Additive / tolerate-absent.' }
7678
7727
  ts: { type: integer }
7679
7728
  FleetFrame_hook_notice:
7680
- type: object
7681
7729
  description: >
7682
- server 1.280.0 (cli [1786]) — a hook adjudication FAILED TO COMPLETE this cycle (observability frame,
7683
- pure observe: it does not block, resume, or inject anything). Semantics are "could not evaluate", NOT
7684
- "evaluated to fail" — render as "this cycle went unguarded, allowed through", never "the guard is broken".
7685
- Wire is FLAT (`send("hook_notice", { type, ...wire, ts })`, http/server.ts SSE outlet — the server-internal
7686
- `{notice}` nesting never reaches the wire). Visibility is fail-CLOSED like bg_notification: the owner keys
7687
- ownerScope/ownerSessionId gate delivery and are STRIPPED before send.
7688
- required: [type, kind, event, reason, ts]
7730
+ Hook observability frame, TWO kinds (both pure observe — never block, resume, or inject anything;
7731
+ visibility fail-CLOSED like bg_notification: the owner keys ownerScope/ownerSessionId gate delivery
7732
+ and are STRIPPED before send; wire is FLAT — `send("hook_notice", { type, ...wire, ts })`, the
7733
+ server-internal `{notice}` nesting never reaches it). codex R1-F4: modeled as the discriminated union
7734
+ it really is — the common `{type, ts}` frame base composed with each kind's payload arm — so a
7735
+ generated client gets the SAME per-kind narrowing as the TS type (a second-family frame missing
7736
+ hookName/entryType is invalid, not silently accepted). `kind` is CLOSED two-member on the server but
7737
+ OPEN ON READ: degrade an unknown future kind to a generic observability row.
7738
+ oneOf:
7739
+ - allOf:
7740
+ - $ref: '#/components/schemas/FleetHookNoticeFrameBase'
7741
+ - $ref: '#/components/schemas/FleetHookDecisionUnavailable'
7742
+ - allOf:
7743
+ - $ref: '#/components/schemas/FleetHookNoticeFrameBase'
7744
+ - $ref: '#/components/schemas/FleetHookNonBlockingFailure'
7745
+
7746
+ FleetHookNoticeFrameBase:
7747
+ type: object
7748
+ description: 'The hook_notice frame envelope shared by both kinds: the SSE frame discriminant and the server timestamp.'
7749
+ required: [type, ts]
7689
7750
  properties:
7690
7751
  type: { const: hook_notice }
7691
- kind:
7692
- type: string
7693
- enum: [hook_decision_unavailable]
7694
- description: 'Only one kind today; an enum slot so the next observability frame kind needs no new frame arm.'
7695
- event: { type: string, description: 'Which hook event (Stop / PreToolUse / …) — defined by "a hook adjudication did not complete", not any single feature.' }
7696
- reason:
7697
- type: string
7698
- enum: [no_content, unparsed, skipped]
7699
- description: 'Machine-branchable cause (same taxonomy as the server''s structured log lines). CLOSED on the server side but OPEN ON READ — an unknown future value must not crash a consumer.'
7700
- detail: { type: string, description: 'Redacted supplement (e.g. why skipped). Additive / tolerate-absent.' }
7701
7752
  ts: { type: integer }
7702
7753
 
7703
7754
  TraceStreamEvent:
@@ -8806,10 +8857,12 @@ components:
8806
8857
  # had no arm to switch on and dropped approval cards. Each arm is `allOf: [<the frame schema>, the
8807
8858
  # narrowed discriminant]` — the key set stays owned by ToolApprovalFrame / ApprovalRequestFrame,
8808
8859
  # so a frame gaining a key (7.5.0's governanceForced) needs no edit here.
8809
- # `approval_revoke` is deliberately ABSENT: it is live-only and never appended.
8860
+ # `approval_revoke` joined as the FOURTH arm ([5924]/S-58, server >= 7.55.0): the bg/resume durable
8861
+ # legs append it to the run's ledger now (the sync leg stays live-SSE-only), so it replays here too.
8810
8862
  - $ref: '#/components/schemas/Event_tool_approval'
8811
8863
  - $ref: '#/components/schemas/Event_tool_approval_complete'
8812
8864
  - $ref: '#/components/schemas/Event_approval_request'
8865
+ - $ref: '#/components/schemas/Event_approval_revoke'
8813
8866
  discriminator:
8814
8867
  propertyName: type
8815
8868
  mapping:
@@ -8852,6 +8905,7 @@ components:
8852
8905
  tool_approval: '#/components/schemas/Event_tool_approval'
8853
8906
  tool_approval_complete: '#/components/schemas/Event_tool_approval_complete'
8854
8907
  approval_request: '#/components/schemas/Event_approval_request'
8908
+ approval_revoke: '#/components/schemas/Event_approval_revoke'
8855
8909
 
8856
8910
  # design/99 §E2 (SHIPPED, core TaskEventIdentity) — additive per-event identity on every CONTENT event (NOT on
8857
8911
  # the lifecycle arms turn_end/compacted/suspended/done/failed). eventId = uuidv7 dedup/resume handle (the durable
@@ -10195,9 +10249,14 @@ components:
10195
10249
  clears that batch's local cards (whitelist-pick by `askIds`) and waits for the new askIds a resume mints.
10196
10250
 
10197
10251
  Siblings already DECIDED are NOT in `askIds` (an accepted decision is not affected by revocation).
10198
- Revoke frames CAN BE LOST (frames produced by the reconciler / orphan legs have no seq to allocate and
10199
- ride the live plane only) — the structural compensation is the open-stream preamble baseline (see
10200
- ApprovalRequestFrame), not a redelivery of this frame.
10252
+ Emission is PER CONTEXT (S-58, server >= 7.55.0 — the old "reconciler/orphan legs have no seq, live
10253
+ plane only" wording pinned a mint-site constraint on the delivery plane and is retired): the sync leg
10254
+ stays live-SSE-only, the bg/resume durable legs append the frame to the run's own ledger and
10255
+ GET /v1/runs/:id/events replays it (see Event_approval_revoke). Revoke frames CAN STILL BE LOST on any
10256
+ leg (shell offline, connection drop, emit-target churn, ledger write failure — the frame is a
10257
+ notification, the row is the source of truth) — the structural compensation is the open-stream preamble
10258
+ baseline (see ApprovalRequestFrame), not a redelivery of this frame; a ledger-replayed revoke frame is
10259
+ for timeline rendering only.
10201
10260
  required: [type, schemaVersion, batchId, askIds, reason, serverNowMs]
10202
10261
  additionalProperties: true
10203
10262
  properties:
@@ -10212,6 +10271,15 @@ components:
10212
10271
  `aborted` = the run was cancelled. Read as OPEN: an unknown reason is handled as a generic revoke
10213
10272
  (clear the cards), never specially.
10214
10273
  serverNowMs: { type: integer }
10274
+ taskId:
10275
+ type: string
10276
+ description: >
10277
+ S-58 (server >= 7.55.0, always sent there; ABSENT on <= 7.54.0 — the frame family was live-only
10278
+ then, hence not in `required`): the ORIGIN run''s wire id (= the `taskId` of the same ask''s card
10279
+ frame; server buildRevokeFrame''s originTaskId). The dispatch set is session-shaped ((owner,
10280
+ sessionId) closure) and can contain OTHER runs'' contexts — durable legs ledger the frame into
10281
+ their own run, so without this key an orphan revoke row (no paired card frame) could not be
10282
+ attributed or filtered; consumers ignore frames whose taskId is not theirs.
10215
10283
 
10216
10284
  AskDecidedConflictBody:
10217
10285
  allOf:
@@ -10878,6 +10946,30 @@ components:
10878
10946
  required: [type]
10879
10947
  properties:
10880
10948
  type: { type: string, enum: [approval_request] }
10949
+ Event_approval_revoke:
10950
+ description: >
10951
+ The design/172 batch-level card REVOCATION frame as an AgentEvent arm ([5924]/S-58, server >= 7.55.0).
10952
+ Emission is PER CONTEXT: the sync stream leg carries it live-SSE-only (unchanged, never ledgered),
10953
+ while the bg/resume durable legs append it to the run's own ledger — so GET /v1/runs/:id/events
10954
+ tails/replays it, and a durable consumer can finally tell "actively revoked (halt/cancel/park
10955
+ degradation)" from "stream ended". On <= 7.54.0 the durable leg never carries this frame.
10956
+
10957
+ 🔴 THIS ARM IS THE OPEN ENVELOPE, NOT `ApprovalRevokeFrame` — same ruling as Event_approval_request:
10958
+ narrow with `schemaVersion == 1` (SDK: `isApprovalRevokeFrameV1`) before touching
10959
+ `batchId`/`askIds`/`taskId`; a frame that does not narrow is handled as a generic revoke (clear that
10960
+ batch's local cards), never specially.
10961
+
10962
+ 🔴 Consumption discipline: (a) attribute/filter by `taskId` (always present >= 7.55.0) — a run that
10963
+ joined the dispatch set late can carry an ORPHAN revoke ledger row with no paired card frame; "not
10964
+ mine" is safely ignored. (b) A replayed revoke frame is for TIMELINE RENDERING ONLY — the card-set
10965
+ reconciliation baseline stays the open-stream preamble (the frame can be lost on any leg: it is a
10966
+ notification, the row is the source of truth). (c) Siblings already DECIDED are never in `askIds`.
10967
+ allOf:
10968
+ - $ref: '#/components/schemas/ApprovalFrameEnvelope'
10969
+ - type: object
10970
+ required: [type]
10971
+ properties:
10972
+ type: { type: string, enum: [approval_revoke] }
10881
10973
 
10882
10974
  # ── resources/*.ts schema backfill, batch 2 (2026-07-28) — the 28-item WIRE_PENDING ratchet zeroed.
10883
10975
  # Each schema below is cross-checked against the server source (file:line cited in its description
@@ -10994,21 +11086,31 @@ components:
10994
11086
  parentToolCallId: { type: string, description: 'The parent tool_use id VERBATIM (E2 domain, engine-minted) — [1832] P1-2, server >= 1.290 / engine 1.432. Additive / tolerate-absent.' }
10995
11087
 
10996
11088
  FleetHookNotice:
11089
+ description: >
11090
+ Hook observability payload, TWO kinds (service fleet-bus.ts `HookNotice` minus the wire-stripped
11091
+ ownerScope/ownerSessionId — the payload view of FleetFrame_hook_notice; a discriminated union on
11092
+ `kind`, mirroring the SDK type verbatim). Both kinds are pure observe — never block, resume, or
11093
+ inject. Visibility is fail-CLOSED: a ?session= subscriber only receives notices provably owned by
11094
+ that session. `kind` is a CLOSED two-member set on the server (exhaustive-switch discipline) but
11095
+ OPEN ON READ: degrade an unknown future kind to a generic observability row, never crash.
11096
+ oneOf:
11097
+ - $ref: '#/components/schemas/FleetHookDecisionUnavailable'
11098
+ - $ref: '#/components/schemas/FleetHookNonBlockingFailure'
11099
+ discriminator:
11100
+ propertyName: kind
11101
+ mapping:
11102
+ hook_decision_unavailable: '#/components/schemas/FleetHookDecisionUnavailable'
11103
+ hook_non_blocking_failure: '#/components/schemas/FleetHookNonBlockingFailure'
11104
+
11105
+ FleetHookDecisionUnavailable:
10997
11106
  type: object
10998
11107
  description: >
10999
- A hook adjudication FAILED TO COMPLETE this cycle (service fleet-bus.ts `HookNotice` minus the
11000
- wire-stripped ownerScope/ownerSessionId — the payload view of FleetFrame_hook_notice). Semantics
11001
- are "could not evaluate", NOT "evaluated to fail": render as "this cycle went unguarded, allowed
11002
- through", never "the guard is broken". Pure observe — it does not block, resume, or inject.
11003
- Visibility is fail-CLOSED: a ?session= subscriber only receives notices provably owned by that
11004
- session.
11108
+ Kind 1 — a hook adjudication FAILED TO COMPLETE this cycle ("could not evaluate", NOT "evaluated to
11109
+ fail": render as "this cycle went unguarded, allowed through", never "the guard is broken").
11005
11110
  required: [kind, event, reason]
11006
11111
  additionalProperties: true
11007
11112
  properties:
11008
- kind:
11009
- type: string
11010
- enum: [hook_decision_unavailable]
11011
- description: 'Only one kind today; an enum slot so the next observability frame kind needs no new frame arm.'
11113
+ kind: { type: string, enum: [hook_decision_unavailable] }
11012
11114
  event: { type: string, description: 'Which hook event (Stop / PreToolUse / …) — defined by "a hook adjudication did not complete", not any single feature.' }
11013
11115
  reason:
11014
11116
  # 🔴 NO `enum` — same ruling as `FleetTaskRow.retiredBy` (codex R1-F3, family case): the description
@@ -11016,9 +11118,31 @@ components:
11016
11118
  # so a closed enum here would make a strict generated client drop the whole hook_notice frame the day the
11017
11119
  # server mints a fourth cause word — and that frame is the ONLY disclosure that a guard cycle went unwatched.
11018
11120
  type: string
11019
- description: 'Machine-branchable cause. CLOSED on the server side (fleet-bus.ts HookNotice.reason) but OPEN ON READ — THE KNOWN WORDS TODAY ARE no_content | unparsed | skipped (named here rather than pinned as an `enum`, deliberately — see the comment above): branch known values, render anything else as the generic "could not evaluate".'
11121
+ description: 'Machine-branchable cause. CLOSED on the server side (fleet-bus.ts) but OPEN ON READ — KNOWN WORDS TODAY: no_content | unparsed | skipped (named here rather than pinned as an `enum`, deliberately — see the comment above): branch known values, render anything else as the generic "could not evaluate".'
11020
11122
  detail: { type: string, description: 'Redacted supplement (e.g. why skipped). Additive / tolerate-absent.' }
11021
11123
 
11124
+ FleetHookNonBlockingFailure:
11125
+ type: object
11126
+ description: >
11127
+ Kind 2 (server >= 7.48.0, #281 — A-075.17): the CONFIGURED HOOK ITSELF BROKE (non-blocking failure:
11128
+ exit nonzero-and-not-2 / timeout / spawn failure / bad JSON). Render "<hookName> hook error" + stderr
11129
+ (CC-parity attachment shape) — this one IS "this hook is broken", unlike kind 1.
11130
+ required: [kind, event, reason, hookName, entryType]
11131
+ additionalProperties: true
11132
+ properties:
11133
+ kind: { type: string, enum: [hook_non_blocking_failure] }
11134
+ event: { type: string, description: 'Which hook event (PreToolUse / Stop / …).' }
11135
+ reason:
11136
+ # 🔴 NO `enum` — same open-on-read ruling as kind 1 (SDK type is `... | (string & {})`).
11137
+ type: string
11138
+ description: 'Machine-branchable failure shape. CLOSED server-side, OPEN ON READ — KNOWN WORDS TODAY: exit_nonzero | timeout | spawn_failed | bad_json.'
11139
+ hookName: { type: string, description: 'Hook identity (statusMessage, else command/URL/prompt; redacted + bounded, http entries stripped of query/fragment). Always sent.' }
11140
+ entryType: { type: string, description: 'command | http | prompt | agent — without it, hookName''s nature is a guess. Closed server-side, open on read. Always sent.' }
11141
+ exitCode: { type: integer, description: 'Absent for timeout/spawn_failed (no exit code exists — the server never mints a legit-looking 0).' }
11142
+ toolName: { type: string, description: 'Present on tool events (PreToolUse/PostToolUse/PostToolUseFailure).' }
11143
+ stderr: { type: string, description: 'Redacted + truncated stderr digest (512-char cap incl. marker). Empty stderr => absent.' }
11144
+ detail: { type: string, description: 'Redacted supplement (e.g. where an exit-2 had no venue). Additive / tolerate-absent.' }
11145
+
11022
11146
  BakeStatus:
11023
11147
  # 新(census 批2 四段)——server `BakeStatus`(plugins/store-contracts.ts), the COARSE lifecycle
11024
11148
  # bakeView/claimResponse/bakesCreate all key on.
@@ -12128,29 +12252,45 @@ components:
12128
12252
  never hand it to another user.
12129
12253
  expiresAtMs: { type: integer, description: 'Absolute server-clock expiry (the window is 10 minutes — one interaction, not a session).' }
12130
12254
 
12255
+ CcImportRedeemedMember:
12256
+ type: object
12257
+ description: >
12258
+ One member of the redeem 200 (core `RedeemedBatchMember`, the 200-REACHABLE arm verbatim — core d.ts
12259
+ permission-rule-consent.d.ts). The union's third arm `{status:"refused", reason}` is STRUCTURALLY
12260
+ UNREACHABLE on this route's 200: any refused member makes the server treat the whole redeem as
12261
+ indeterminate, release the claim and answer 503 `state.rule_import_retry` (server rules-consent.ts) —
12262
+ so this schema honestly describes the two-value `status` only.
12263
+ additionalProperties: false
12264
+ required: [candidateIndex, rule, scope, status, alreadyRedeemed, dot]
12265
+ properties:
12266
+ candidateIndex: { type: integer, description: 'Index into the prepare preview''s candidate set (candidate space).' }
12267
+ rule: { type: string, description: 'Canonical rule text.' }
12268
+ scope: { $ref: '#/components/schemas/RuleScope' }
12269
+ status:
12270
+ type: string
12271
+ enum: [persisted, deduped]
12272
+ description: '`persisted` = landed this redeem; `deduped` = an equal rule was already in the store (the consent took effect — not a failure).'
12273
+ alreadyRedeemed: { type: boolean, description: 'true = this outcome was REPLAYED verbatim from the ticket row (lost-response retry; idempotency evidence — zero double-mint).' }
12274
+ dot: { $ref: '#/components/schemas/RuleDot' }
12275
+
12131
12276
  CcImportResult:
12132
12277
  type: object
12133
12278
  description: >
12134
- What the import ACTUALLY did (core `ImportResult`) — a different moment and a different contract from
12135
- the preview, because dedup, concurrency and redemption-time validation can each move an entry between
12136
- the two.
12279
+ What the import ACTUALLY did (server >= 7.46.0, BREAKING #2 there / core 5.58.0 redeemRuleBatch
12280
+ members passthrough) — a different moment and a different contract from the preview, because dedup,
12281
+ concurrency and redemption-time validation can each move an entry between the two.
12137
12282
 
12138
- ⚠️ `skippedAtRedeem` is empty on every success arm of THIS lane: the server treats a non-empty one as
12139
- INDETERMINATE, releases the claim and answers 503 `state.rule_import_retry` instead of returning a 200
12140
- that quietly means "half of it did not land". The field stays on the shape because it is core's.
12283
+ 🔴 SHAPE CHANGE (A-075.13): the old three-bucket form `{persisted[], deduped[], skippedAtRedeem[],
12284
+ rev}` left the wire in server 7.46.0 — a consumer reading `result.persisted.length` gets undefined.
12285
+ This schema describes the real wire since then; the SDK type changed with it (a staleness fix, not a
12286
+ behavior change).
12141
12287
  additionalProperties: false
12142
- required: [persisted, deduped, skippedAtRedeem, rev]
12288
+ required: [members, rev]
12143
12289
  properties:
12144
- persisted:
12145
- type: array
12146
- items: { $ref: '#/components/schemas/RuleCandidate' }
12147
- deduped:
12290
+ members:
12148
12291
  type: array
12149
- items: { $ref: '#/components/schemas/RuleCandidate' }
12150
- description: 'Already in the store — not a failure.'
12151
- skippedAtRedeem:
12152
- type: array
12153
- items: { $ref: '#/components/schemas/CcImportSkippedRule' }
12292
+ items: { $ref: '#/components/schemas/CcImportRedeemedMember' }
12293
+ description: 'Per-candidate outcome (discriminate on `status`; refused never rides a 200 — see CcImportRedeemedMember).'
12154
12294
  rev: { type: integer, description: 'The rule store''s monotonic revision after the batch.' }
12155
12295
 
12156
12296
  CcImportRedeemResult:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/sdk",
3
- "version": "7.4.0",
3
+ "version": "8.1.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",