@sema-agent/sdk 4.0.1 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -1
- package/dist/client.d.ts +10 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +7 -2
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +42 -5
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +81 -7
- package/dist/errors.js.map +1 -1
- package/dist/events.d.ts +76 -4
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js.map +1 -1
- package/dist/health.d.ts +2 -2
- package/dist/health.js +1 -1
- package/dist/idempotency.d.ts +11 -1
- package/dist/idempotency.d.ts.map +1 -1
- package/dist/idempotency.js +11 -1
- package/dist/idempotency.js.map +1 -1
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/resources/approvals.d.ts +43 -13
- package/dist/resources/approvals.d.ts.map +1 -1
- package/dist/resources/approvals.js +35 -12
- package/dist/resources/approvals.js.map +1 -1
- package/dist/resources/assistant.d.ts +21 -4
- package/dist/resources/assistant.d.ts.map +1 -1
- package/dist/resources/assistant.js +10 -3
- package/dist/resources/assistant.js.map +1 -1
- package/dist/resources/fleet.d.ts +8 -3
- package/dist/resources/fleet.d.ts.map +1 -1
- package/dist/resources/fleet.js +2 -1
- package/dist/resources/fleet.js.map +1 -1
- package/dist/resources/runs.d.ts +89 -18
- package/dist/resources/runs.d.ts.map +1 -1
- package/dist/resources/runs.js +53 -17
- package/dist/resources/runs.js.map +1 -1
- package/dist/resources/sessions.d.ts +10 -1
- package/dist/resources/sessions.d.ts.map +1 -1
- package/dist/resources/sessions.js +10 -1
- package/dist/resources/sessions.js.map +1 -1
- package/dist/resources/tool-approvals.d.ts +8 -5
- package/dist/resources/tool-approvals.d.ts.map +1 -1
- package/dist/resources/tool-approvals.js +2 -1
- package/dist/resources/tool-approvals.js.map +1 -1
- package/dist/sse.d.ts +58 -14
- package/dist/sse.d.ts.map +1 -1
- package/dist/sse.js +88 -15
- package/dist/sse.js.map +1 -1
- package/dist/transport.d.ts +14 -1
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +20 -5
- package/dist/transport.js.map +1 -1
- package/dist/types.d.ts +139 -44
- package/dist/types.d.ts.map +1 -1
- package/openapi.yaml +316 -12
- package/package.json +1 -1
package/openapi.yaml
CHANGED
|
@@ -494,12 +494,20 @@ paths:
|
|
|
494
494
|
turn (FIFO), spread across turns. FORWARD-DRAFT: core's steer is harness-level today, not
|
|
495
495
|
per-call; the per-call mapping is pending D-A core.
|
|
496
496
|
responses:
|
|
497
|
-
'200':
|
|
497
|
+
'200':
|
|
498
|
+
description: Steer accepted and APPLIED to the live run on this replica (`delivery:"applied"`).
|
|
499
|
+
content:
|
|
500
|
+
application/json:
|
|
501
|
+
schema: { $ref: '#/components/schemas/SteerReceipt' }
|
|
498
502
|
'202':
|
|
499
503
|
description: >-
|
|
500
|
-
Steer accepted and
|
|
501
|
-
|
|
502
|
-
(`
|
|
504
|
+
Steer accepted and PARKED. Two shapes share this code — branch on `delivery`, not the status:
|
|
505
|
+
a durable-`suspended` run parks on its pending checkpoint (`delivery:"queued"`) and drains on resume;
|
|
506
|
+
an ALREADY-ENDED run gets a freshly-minted `task_done` checkpoint (`delivery:"parked_for_wake"`) and
|
|
507
|
+
the message is delivered only by POST /v1/sessions/{sessionId}/wake.
|
|
508
|
+
content:
|
|
509
|
+
application/json:
|
|
510
|
+
schema: { $ref: '#/components/schemas/SteerReceipt' }
|
|
503
511
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
504
512
|
'404': { $ref: '#/components/responses/NotFound' }
|
|
505
513
|
'409':
|
|
@@ -2070,7 +2078,17 @@ paths:
|
|
|
2070
2078
|
application/json:
|
|
2071
2079
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
2072
2080
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
2073
|
-
'404':
|
|
2081
|
+
'404':
|
|
2082
|
+
description: >
|
|
2083
|
+
Owner-gate / unknown session (no existence oracle), OR — [2400] CB-2, declared 2026-08-02 — the core
|
|
2084
|
+
code `checkpoint.not_found`: the pending checkpoint this decide addressed is gone. It is the ONE
|
|
2085
|
+
member of the mirrored `checkpoint.*` family the server sends as a 404 rather than a 409
|
|
2086
|
+
(`src/http/server.ts:2199`: `e.code === "checkpoint.not_found" ? 404 : 409`), so the SDK maps it to
|
|
2087
|
+
NotFoundError while the rest of the family maps to ConflictError. Client action: refetch the inbox —
|
|
2088
|
+
do not retry this decide.
|
|
2089
|
+
content:
|
|
2090
|
+
application/json:
|
|
2091
|
+
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
2074
2092
|
'409':
|
|
2075
2093
|
description: >
|
|
2076
2094
|
Either a session-CAS conflict (`ErrorResponse.activeTaskId`), OR a design/80 D-1
|
|
@@ -2078,6 +2096,20 @@ paths:
|
|
|
2078
2096
|
NOT match the current pending action (TOCTOU/swap). The SDK splits these by `errorCode` into
|
|
2079
2097
|
ConflictError vs ApprovalBindingMismatchError. binding_mismatch = SAFETY signal: refetch + re-present
|
|
2080
2098
|
to the human, NEVER auto-retry.
|
|
2099
|
+
FOURTH member ([2400] CB-2, declared 2026-08-02): `gate_not_tool_approval` — the suspension this
|
|
2100
|
+
sessionId is parked on is NOT a tool-approval gate (`src/http/server.ts:1581` rejects pre-CAS when the
|
|
2101
|
+
gate kind is neither `human` nor `irreversible_ask`: nothing is consumed, no model leg burns). It is
|
|
2102
|
+
the THIRD member of the wrong-door guard family alongside `gate_not_resumable` (§4b) and
|
|
2103
|
+
`gate_not_plan_review` (§4c) → SDK `GateNotToolApprovalError`. Client action: route by the row's
|
|
2104
|
+
`gateKind` — `plan_review` → `POST /v1/assistant/tasks/{taskId}/plan_review`, `resource_limit` →
|
|
2105
|
+
`POST /v1/assistant/tasks/{taskId}/resume`. Retrying the same body never succeeds.
|
|
2106
|
+
FIFTH group ([2400] CB-2): the core `checkpoint.*` family the server mirrors verbatim
|
|
2107
|
+
(`src/http/server.ts:2199-2206`) — `checkpoint.gate_mismatch` / `checkpoint.reopen_failed` /
|
|
2108
|
+
`checkpoint.reopen_revote` / `checkpoint.already_exists` / `checkpoint.resume_aborted` /
|
|
2109
|
+
`checkpoint.unsupported_version` all arrive as 409 and fall on the SDK's `checkpoint.` PREFIX family
|
|
2110
|
+
(→ ConflictError, `.errorCode` carried verbatim; an OPEN set, so a future core code degrades with
|
|
2111
|
+
information instead of collapsing anonymously). The one non-409 member is `checkpoint.not_found`,
|
|
2112
|
+
which the same mint point sends as a 404 (see below).
|
|
2081
2113
|
THIRD member (moved here from a documented-but-nonexistent 410, 2026-07-31): `approval_stale`
|
|
2082
2114
|
(`errorCode`; `terminal:"resolved"` when attributable, else the key is absent) — the checkpoint is
|
|
2083
2115
|
already terminal (someone resolved it / abandonment-TTL GC / SLA resolve-deny). Client action:
|
|
@@ -3981,6 +4013,17 @@ components:
|
|
|
3981
4013
|
objective:
|
|
3982
4014
|
type: string
|
|
3983
4015
|
description: The task. Put per-request context here (keep `systemPrompt` stable/cacheable).
|
|
4016
|
+
taskId:
|
|
4017
|
+
type: string
|
|
4018
|
+
description: >-
|
|
4019
|
+
[2400] TR-16 (declared 2026-08-02) — CALLER-MINTED uuidv7 task id: the DURABLE second tier of
|
|
4020
|
+
idempotency on POST /v1/runs (`src/http/routes/runs.ts:196-217`). The `Idempotency-Key` header's
|
|
4021
|
+
cache is in-memory and PER-POD, so a dispatch gateway that re-routes a retry to ANOTHER instance
|
|
4022
|
+
after a network error would start a SECOND run; THIS replay reads the durable run store, so it
|
|
4023
|
+
survives the re-route and a restart — it is the prerequisite for gateway failover. A hit replays the
|
|
4024
|
+
original 202 receipt (`{taskId, sessionId, status}`); nothing re-runs, nothing re-bills.
|
|
4025
|
+
Shape-gated: a non-uuidv7 value is 400 `request.id_invalid`. Owner-gated: a taskId owned by another
|
|
4026
|
+
principal answers 409 `conflict.run_exists` (no cross-tenant id oracle). Omit ⇒ the server mints one.
|
|
3984
4027
|
scenario: { $ref: '#/components/schemas/Scenario' }
|
|
3985
4028
|
sessionId:
|
|
3986
4029
|
type: string
|
|
@@ -4291,6 +4334,9 @@ components:
|
|
|
4291
4334
|
[2255]① reject-shape material (server >=3.21, SSE lane): on a `conflict.session_active_run`
|
|
4292
4335
|
rejection the stream's terminal `done` frame carries the occupying run's taskId. On wire since
|
|
4293
4336
|
[1833] G10; registered here late. ADDITIVE / tolerate-absent — normal terminal frames omit it.
|
|
4337
|
+
⚠️ 契约调和车1 E(2026-08-02):that rejection frame is NOT a TaskResult at all — it has its own
|
|
4338
|
+
schema `ActiveRunConflictDoneResult` (no taskId/sessionId/stats). These three keys stay here for
|
|
4339
|
+
the POLLED shapes that may still echo them; the SSE rejection reads them off the union's other arm.
|
|
4294
4340
|
activeTaskStatus:
|
|
4295
4341
|
type: string
|
|
4296
4342
|
description: >
|
|
@@ -4773,6 +4819,20 @@ components:
|
|
|
4773
4819
|
description: >
|
|
4774
4820
|
Approve-with-edit (design/37 last-wins): operator's rewritten tool args, applied AFTER the binding
|
|
4775
4821
|
check. `boundInputHash` STILL binds the ORIGINAL input the human saw — never hash updatedInput.
|
|
4822
|
+
remember:
|
|
4823
|
+
type: string
|
|
4824
|
+
enum: [session]
|
|
4825
|
+
description: >-
|
|
4826
|
+
[2400] HITL-4 (declared 2026-08-02) — the "don't ask again in this session" grant: lands a
|
|
4827
|
+
per-session, per-toolName approval EXEMPTION alongside the decision (server
|
|
4828
|
+
`routes/approvals-assistant.ts` reads it; the SDK has typed it since the facade audit, the spec had
|
|
4829
|
+
not). It is an approval MEMORY, not a policy loosen — a deny / neverAuto always outranks it.
|
|
4830
|
+
Constraints (all server-enforced): only with `decision:"approve"` (else 400
|
|
4831
|
+
`request.field_conflict`); requires the D-1 binding echo in the same body (else 400
|
|
4832
|
+
`remember_requires_binding`); REFUSED on a direct-door worker (400 `remember_not_in_proof` — it is
|
|
4833
|
+
not inside the HMAC payload, so accepting it unsigned would be tamperable); 501 without an exemption
|
|
4834
|
+
store. On the parked-background-agent leg the grant lands on the child's ROOT/HOST session (the whole
|
|
4835
|
+
session tree shares it). The 200 body echoes `rememberApplied` when a store is wired.
|
|
4776
4836
|
|
|
4777
4837
|
ApprovalRow:
|
|
4778
4838
|
type: object
|
|
@@ -4881,6 +4941,16 @@ components:
|
|
|
4881
4941
|
browse: { type: boolean }
|
|
4882
4942
|
archive: { type: boolean }
|
|
4883
4943
|
maxFileBytes: { type: integer }
|
|
4944
|
+
sessionEvents:
|
|
4945
|
+
type: boolean
|
|
4946
|
+
description: >
|
|
4947
|
+
🔴 契约调和车1 H② (2026-08-02): server HAS been emitting this key (`src/http/routes/capabilities.ts:70`)
|
|
4948
|
+
while both this spec and the SDK type were missing it. Gates `GET /v1/sessions/{sessionId}/events`
|
|
4949
|
+
(the session-level SSE head subscription). Predicate is a THREE-way AND: a durable session-watch seam
|
|
4950
|
+
plus a session store exposing BOTH `getLeafId` and `ownerOf` — the route's 501 uses the same
|
|
4951
|
+
predicate, so "says yes <=> route works" holds here. False/absent => fall back to polling
|
|
4952
|
+
`GET /v1/sessions/{sessionId}/head`. NOTE (server [2373]A-5): no consumer is wired to it yet — it is
|
|
4953
|
+
a prepared slot, correct to gate on, wrong to read as "widely consumed".
|
|
4884
4954
|
policy: { type: boolean, description: "`GET /v1/policy` (autonomy/permission READ side)." }
|
|
4885
4955
|
permissionModeWrite: { type: boolean, description: "Runtime permission-mode WRITE. Advertised false by design — autonomy is CONFIG, not steer; the READ side is `policy`." }
|
|
4886
4956
|
modelSelection: { type: boolean, description: "`model` accepted per request." }
|
|
@@ -4906,18 +4976,39 @@ components:
|
|
|
4906
4976
|
askUserQuestion: { type: boolean, description: "AskUserQuestion gate is available (durable when approvals are)." }
|
|
4907
4977
|
toolApproval: { type: boolean, description: "Tool-approval gating is active." }
|
|
4908
4978
|
promptSuggestions: { type: boolean, description: "Follow-up prompt suggestions are generated." }
|
|
4909
|
-
modelUsage:
|
|
4979
|
+
modelUsage:
|
|
4980
|
+
type: boolean
|
|
4981
|
+
description: >
|
|
4982
|
+
Per-model usage echo is available (server `src/http/routes/capabilities.ts:197`
|
|
4983
|
+
`Boolean(runStore && modelUsage)` — BOTH the durable run store and the tracker that feeds it;
|
|
4984
|
+
absent either, a consumer only gets aggregate cost).
|
|
4985
|
+
🔴 CORRECTED (契约调和车1 H③, 2026-08-02): this bit does NOT gate a read route — the route this
|
|
4986
|
+
description used to name (`GET /v1/runs/:id/model-usage`) DOES NOT EXIST on any server (no route
|
|
4987
|
+
case anywhere in the tree); probing it writes a guaranteed 404. What it really gates: the
|
|
4988
|
+
`model_usage` event arm on the run stream (per-model token/cost DELTAS) and the terminal
|
|
4989
|
+
`TaskStats.modelUsage` (sum across every leg).
|
|
4910
4990
|
scheduler: { type: boolean, description: "Assistant-scheduler face is mounted." }
|
|
4911
4991
|
sendUserFile: { type: boolean, description: "Outbound user-file delivery is wired." }
|
|
4912
4992
|
sendUserFileLedger: { type: boolean, description: "The send-file ledger (audit of deliveries) is available." }
|
|
4913
4993
|
excludeTools:
|
|
4914
4994
|
type: array
|
|
4915
4995
|
items: { type: string }
|
|
4916
|
-
description:
|
|
4996
|
+
description: >
|
|
4997
|
+
⚠️ PHANTOM KEY — NEVER emitted by any server version (契约调和车1 H①, 2026-08-02: verified against
|
|
4998
|
+
every casting site in `src/http/routes/capabilities.ts`). It is a **TaskRequest** field (submit-body
|
|
4999
|
+
validation `src/http/server.ts:1358`, TaskSpec mapping `src/boot/resolve-spec.ts:588`) that was
|
|
5000
|
+
mis-registered on the capability face. Reading it always yields absent. Kept (removing it is a
|
|
5001
|
+
breaking change) — SCHEDULED FOR REMOVAL IN THE NEXT MAJOR.
|
|
5002
|
+
Semantics, for the archive: roster TRUE-UNMOUNT — the named tools' schema bytes never reach the
|
|
5003
|
+
model and the assembly manifest narrows honestly; tighten-only, unioned into every child spawn.
|
|
4917
5004
|
deferTools:
|
|
4918
5005
|
type: array
|
|
4919
5006
|
items: { type: string }
|
|
4920
|
-
description:
|
|
5007
|
+
description: >
|
|
5008
|
+
⚠️ PHANTOM KEY — NEVER emitted by any server version; same mis-registration as `excludeTools`, and
|
|
5009
|
+
the real thing is the **TaskRequest** field of this name. SCHEDULED FOR REMOVAL IN THE NEXT MAJOR.
|
|
5010
|
+
Semantics, for the archive: DEFERRED DISCLOSURE — the named MOUNTED tools ride the wire as a
|
|
5011
|
+
placeholder (schema bytes out of the cache prefix) and materialize via ToolSearch on demand.
|
|
4921
5012
|
s3PublicEndpoint:
|
|
4922
5013
|
type: ["string", "null"]
|
|
4923
5014
|
description: >
|
|
@@ -5895,7 +5986,20 @@ components:
|
|
|
5895
5986
|
properties:
|
|
5896
5987
|
event: { type: string, description: 'SSE event name (open set; dispatch on this).' }
|
|
5897
5988
|
id: { type: string, description: 'The durable seq (id: line) when present — feed back as Last-Event-ID to resume. meta/heartbeat carry none.' }
|
|
5898
|
-
data:
|
|
5989
|
+
data:
|
|
5990
|
+
type: object
|
|
5991
|
+
additionalProperties: true
|
|
5992
|
+
description: 'The frame JSON data: payload (shape varies by event; permissive).'
|
|
5993
|
+
properties:
|
|
5994
|
+
type:
|
|
5995
|
+
type: string
|
|
5996
|
+
description: >
|
|
5997
|
+
契约调和车1 G(2026-08-02;server [2373]C-12, `src/trace/project.ts:763` + the meta frame at
|
|
5998
|
+
`routes/trace-usage.ts:258`): the frame's own event name, DOUBLE-EMITTED inside `data`. Always
|
|
5999
|
+
present on server >= 5.0.0; OPTIONAL here because the SDK's supported floor is server 3.0.0
|
|
6000
|
+
(where only the `error` frame carried it). Equal to the SSE `event:` line verbatim — its reason
|
|
6001
|
+
to exist is the proxy/relay case that strips the `event:` line and forwards only the data JSON,
|
|
6002
|
+
where this is the only key left to dispatch on. Heartbeats (`data: {}`) carry none.
|
|
5899
6003
|
|
|
5900
6004
|
PendingList:
|
|
5901
6005
|
type: object
|
|
@@ -6732,6 +6836,13 @@ components:
|
|
|
6732
6836
|
- $ref: '#/components/schemas/Event_message_committed'
|
|
6733
6837
|
# [2373]A-2(2026-08-03,server 5.0.0):compaction_outcome 三腿同源批的 spec 半场(SDK 臂 20867e1 同批)。
|
|
6734
6838
|
- $ref: '#/components/schemas/Event_compaction_outcome'
|
|
6839
|
+
# [2400] ch2(SDK 4.2.0):CB-1 流控帽帧 + TR-7 durable 五臂 —— 两侧同缺,见各 schema 处的注。
|
|
6840
|
+
- $ref: '#/components/schemas/Event_error'
|
|
6841
|
+
- $ref: '#/components/schemas/Event_question'
|
|
6842
|
+
- $ref: '#/components/schemas/Event_question_complete'
|
|
6843
|
+
- $ref: '#/components/schemas/Event_elicitation'
|
|
6844
|
+
- $ref: '#/components/schemas/Event_elicitation_complete'
|
|
6845
|
+
- $ref: '#/components/schemas/Event_workflow_complete'
|
|
6735
6846
|
discriminator:
|
|
6736
6847
|
propertyName: type
|
|
6737
6848
|
mapping:
|
|
@@ -6762,6 +6873,12 @@ components:
|
|
|
6762
6873
|
needs_review: '#/components/schemas/Event_needs_review'
|
|
6763
6874
|
message_committed: '#/components/schemas/Event_message_committed'
|
|
6764
6875
|
compaction_outcome: '#/components/schemas/Event_compaction_outcome'
|
|
6876
|
+
error: '#/components/schemas/Event_error'
|
|
6877
|
+
question: '#/components/schemas/Event_question'
|
|
6878
|
+
question_complete: '#/components/schemas/Event_question_complete'
|
|
6879
|
+
elicitation: '#/components/schemas/Event_elicitation'
|
|
6880
|
+
elicitation_complete: '#/components/schemas/Event_elicitation_complete'
|
|
6881
|
+
workflow_complete: '#/components/schemas/Event_workflow_complete'
|
|
6765
6882
|
|
|
6766
6883
|
# design/99 §E2 (SHIPPED, core TaskEventIdentity) — additive per-event identity on every CONTENT event (NOT on
|
|
6767
6884
|
# the lifecycle arms turn_end/compacted/suspended/done/failed). eventId = uuidv7 dedup/resume handle (the durable
|
|
@@ -7502,12 +7619,69 @@ components:
|
|
|
7502
7619
|
|
|
7503
7620
|
Event_done:
|
|
7504
7621
|
type: object
|
|
7505
|
-
description:
|
|
7506
|
-
|
|
7622
|
+
description: >
|
|
7623
|
+
The stream's terminal frame. `result` is a DISCRIMINATED UNION of TWO real shapes (契约调和车1 E,
|
|
7624
|
+
2026-08-02) — do NOT assume the full TaskResult:
|
|
7625
|
+
· `TaskResult` — the normal terminal (output string at `.result`, stats at `.stats`), service Drift 4;
|
|
7626
|
+
· `ActiveRunConflictDoneResult` — the SSE lane's REJECTION terminal: when the session already has an
|
|
7627
|
+
active run, the submit's 409 is encoded as this done frame (`src/http/routes/tasks.ts:234`), and it
|
|
7628
|
+
carries NO `taskId` / `sessionId` / `stats`.
|
|
7629
|
+
Narrow on the presence of `stats` (required on TaskResult, absent from the conflict shape), or on
|
|
7630
|
+
`errorCode === "conflict.session_active_run"`. `status` does NOT discriminate — both shapes carry it.
|
|
7631
|
+
additionalProperties: false # 封闭:帧本身只有 {type,result,replay?};`result` 内部按臂各自裁定(TaskResult 开集,冲突形封闭)
|
|
7507
7632
|
required: [type, result]
|
|
7508
7633
|
properties:
|
|
7509
7634
|
type: { const: done }
|
|
7510
|
-
result:
|
|
7635
|
+
result:
|
|
7636
|
+
oneOf:
|
|
7637
|
+
- $ref: '#/components/schemas/TaskResult'
|
|
7638
|
+
- $ref: '#/components/schemas/ActiveRunConflictDoneResult'
|
|
7639
|
+
replay:
|
|
7640
|
+
type: boolean
|
|
7641
|
+
description: >
|
|
7642
|
+
契约调和车1 F(2026-08-02;server `src/http/routes/tasks.ts:71` 与 `:919` 两处铸造点)— `true`
|
|
7643
|
+
marks the IDEMPOTENT-REPLAY leg: this terminal was NOT produced by a live run of your submit. Either
|
|
7644
|
+
the `Idempotency-Key` hit the in-flight/settled cache (:71), or your call was deduplicated into a
|
|
7645
|
+
concurrent identical submit and received no live events at all (:919). The `result` is the original
|
|
7646
|
+
run's terminal, verbatim. ABSENT on every live leg (never `false`) — a UI can use it to say "replayed"
|
|
7647
|
+
instead of implying the work just ran twice.
|
|
7648
|
+
|
|
7649
|
+
ActiveRunConflictDoneResult:
|
|
7650
|
+
type: object
|
|
7651
|
+
description: >
|
|
7652
|
+
The SSE lane's REJECTION `done.result` (server `src/http/active-run-conflict.ts:64` `toDoneFrameResult`,
|
|
7653
|
+
server >= 3.21). Same material as the 409 `conflict.session_active_run` body, minus the token-free
|
|
7654
|
+
addressing rule's exceptions: a checkpoint token NEVER appears on the wire. It is NOT a TaskResult —
|
|
7655
|
+
there is no run to report on, so `taskId`/`sessionId`/`stats` are structurally absent.
|
|
7656
|
+
# 封闭:铸造点是一个具名 interface(`ActiveRunConflictDoneResult`),逐字挑键 —— 不是透传。
|
|
7657
|
+
additionalProperties: false
|
|
7658
|
+
required: [status, errorCode, errorMessage, activeTaskId]
|
|
7659
|
+
properties:
|
|
7660
|
+
status: { const: failed }
|
|
7661
|
+
errorCode:
|
|
7662
|
+
const: conflict.session_active_run
|
|
7663
|
+
description: '[2373]C-1:与 409 体同一机器码 —— 流腿客户端凭它认拒绝,禁按 byte-frozen 文案匹配。'
|
|
7664
|
+
errorMessage:
|
|
7665
|
+
type: string
|
|
7666
|
+
description: >
|
|
7667
|
+
Human-readable exit route, VARIES by the occupying run's state (running => steer/cancel; parked =>
|
|
7668
|
+
decide at `pendingGate.decidePath` / cancel). Display only — branch on `activeTaskStatus`/`pendingGate`.
|
|
7669
|
+
activeTaskId:
|
|
7670
|
+
type: [string, 'null']
|
|
7671
|
+
description: 'The run occupying the session; `null` when the claim holder could not be identified.'
|
|
7672
|
+
activeTaskStatus:
|
|
7673
|
+
type: string
|
|
7674
|
+
description: '`running` | `suspended` | `needs_review` — best-effort (absent when the store lookup degraded).'
|
|
7675
|
+
pendingGate:
|
|
7676
|
+
type: object
|
|
7677
|
+
required: [kind, decidePath]
|
|
7678
|
+
additionalProperties: false
|
|
7679
|
+
description: >
|
|
7680
|
+
Present when the occupying run is parked on a pending durable gate: `decidePath` is THE ONE correct
|
|
7681
|
+
resume entry for its `kind` (gate-kind routed; sessionId-addressed).
|
|
7682
|
+
properties:
|
|
7683
|
+
kind: { type: string }
|
|
7684
|
+
decidePath: { type: string }
|
|
7511
7685
|
Event_failed:
|
|
7512
7686
|
type: object
|
|
7513
7687
|
# 封闭 + 回填 `activeTaskId`(census 轴一,2026-07-30):[1833] G10 —— session 已有活跃 run 的冲突
|
|
@@ -7624,6 +7798,102 @@ components:
|
|
|
7624
7798
|
sourceTaskId: { type: string }
|
|
7625
7799
|
bgAgentId: { type: string }
|
|
7626
7800
|
|
|
7801
|
+
# ══════════════════════════════════════════════════════════════════════════════════════════════
|
|
7802
|
+
# [2400] 说明书审计 ch2(SDK 4.2.0)补的**六个未登记臂**:一个流控帧(CB-1/TR-6)+ 五个 HITL/workflow
|
|
7803
|
+
# 帧(TR-7)。同一个盲区:`spec-union-arm-gate` 比的是 spec ↔ SDK 两侧的臂集,这六个两侧同缺 ⇒ 那道门
|
|
7804
|
+
# 对它们结构性失明;抓到它们靠的是拿 server 的 `res.write("event: …")` / `append("…")` 铸造点第三方对账。
|
|
7805
|
+
# ══════════════════════════════════════════════════════════════════════════════════════════════
|
|
7806
|
+
Event_error:
|
|
7807
|
+
type: object
|
|
7808
|
+
description: >
|
|
7809
|
+
STREAM-CONTROL frame, NOT a run failure (server src/http/sse-log.ts:86; the trace leg emits the same
|
|
7810
|
+
shape at routes/trace-usage.ts:294). The server writes it as a NAMED frame (`event: error`) whose payload
|
|
7811
|
+
echoes `type`, so both an `event:`-dispatching client and a payload-dispatching one see it.
|
|
7812
|
+
🔴 Its arrival means the RUN IS STILL ALIVE — the 15-minute stream cap fired. The correct handling is to
|
|
7813
|
+
RECONNECT with `Last-Event-ID` and keep reading (the durable leg stamps `id:` on every frame); rendering
|
|
7814
|
+
it as a terminal would declare a live task dead. `done` / `failed` are the terminal arms; this one is not.
|
|
7815
|
+
Known `errorCode`: `STREAM_MAX_DURATION` (open set — branch on the code, degrade unknown codes to the
|
|
7816
|
+
generic "reconnectable stream-control signal").
|
|
7817
|
+
additionalProperties: false
|
|
7818
|
+
required: [type, errorCode]
|
|
7819
|
+
properties:
|
|
7820
|
+
type: { const: error }
|
|
7821
|
+
errorCode: { type: string, description: 'STREAM_MAX_DURATION (open set).' }
|
|
7822
|
+
message: { type: string }
|
|
7823
|
+
Event_question:
|
|
7824
|
+
type: object
|
|
7825
|
+
description: >
|
|
7826
|
+
AskUserQuestion OPEN frame (server src/question.ts:38 `QuestionFrame`). The live leg dispatches it by SSE
|
|
7827
|
+
event name (routes/tasks.ts:677, the same out-of-band channel as `elicitation`/`tool_approval`); the
|
|
7828
|
+
DURABLE leg persists it via `append(type, rest)` (src/runs.ts:498), so the same frame also replays on
|
|
7829
|
+
GET /v1/runs/:id/events — that half is what this schema registers.
|
|
7830
|
+
🔴 UNTRUSTED-for-display: `questions` is secret-redacted, render only, NEVER re-feed to a model.
|
|
7831
|
+
`questions` absent ⇒ the payload exceeded the 16 KiB cap and was dropped (the ask headless-defaults).
|
|
7832
|
+
additionalProperties: false
|
|
7833
|
+
required: [type, questionId]
|
|
7834
|
+
properties:
|
|
7835
|
+
type: { const: question }
|
|
7836
|
+
questionId: { type: string }
|
|
7837
|
+
questions:
|
|
7838
|
+
type: array
|
|
7839
|
+
items: { $ref: '#/components/schemas/AskQuestion' }
|
|
7840
|
+
Event_question_complete:
|
|
7841
|
+
type: object
|
|
7842
|
+
description: >
|
|
7843
|
+
AskUserQuestion CLOSE frame (dialog-dismiss signal). `answered` = a human responded; `unanswered` =
|
|
7844
|
+
ttl / abort / throttle released it and the model got the headless default. Cosmetic — it does not change
|
|
7845
|
+
the run's status.
|
|
7846
|
+
additionalProperties: false
|
|
7847
|
+
required: [type, questionId]
|
|
7848
|
+
properties:
|
|
7849
|
+
type: { const: question_complete }
|
|
7850
|
+
questionId: { type: string }
|
|
7851
|
+
outcome: { type: string, enum: [answered, unanswered] }
|
|
7852
|
+
Event_elicitation:
|
|
7853
|
+
type: object
|
|
7854
|
+
description: >
|
|
7855
|
+
Inbound-MCP elicitation OPEN frame (server src/elicitation.ts:42 `ElicitationFrame`). Same two legs as
|
|
7856
|
+
`question`: live dispatches by event name, the durable leg persists + replays it.
|
|
7857
|
+
🔴 UNTRUSTED: `message` is fenced + secret-redacted; `requestedSchema` is an OPAQUE passthrough (never
|
|
7858
|
+
interpreted/validated) and must still be fenced on display. v1 is always `mode: "form"` (url-mode is
|
|
7859
|
+
rejected upstream as a phishing surface).
|
|
7860
|
+
additionalProperties: false
|
|
7861
|
+
required: [type, elicitationId, mcpServerName]
|
|
7862
|
+
properties:
|
|
7863
|
+
type: { const: elicitation }
|
|
7864
|
+
elicitationId: { type: string }
|
|
7865
|
+
mcpServerName: { type: string }
|
|
7866
|
+
message: { type: string }
|
|
7867
|
+
requestedSchema: {}
|
|
7868
|
+
mode: { type: string, enum: [form] }
|
|
7869
|
+
Event_elicitation_complete:
|
|
7870
|
+
type: object
|
|
7871
|
+
description: 'Inbound-MCP elicitation CLOSE frame; `action` is how it settled (the dialog-dismiss reason).'
|
|
7872
|
+
additionalProperties: false
|
|
7873
|
+
required: [type, elicitationId, mcpServerName]
|
|
7874
|
+
properties:
|
|
7875
|
+
type: { const: elicitation_complete }
|
|
7876
|
+
elicitationId: { type: string }
|
|
7877
|
+
mcpServerName: { type: string }
|
|
7878
|
+
action: { type: string, enum: [accept, decline, cancel] }
|
|
7879
|
+
Event_workflow_complete:
|
|
7880
|
+
type: object
|
|
7881
|
+
description: >
|
|
7882
|
+
Out-of-band delivery of an async workflow's completion (server
|
|
7883
|
+
src/orchestration/workflow-completion-inbox.ts:522). Delivery is STREAM-OPEN driven: the session's inbox
|
|
7884
|
+
is drained on its NEXT leg — the sync leg writes a live frame, the bg/resume legs `append` it as a durable
|
|
7885
|
+
event the tailing client replays.
|
|
7886
|
+
🔴 AT-LEAST-ONCE (two-phase: the entry is acked only after a successful emit, and two legs racing the same
|
|
7887
|
+
session may double-emit) — consumers MUST dedup on `runId`. `summary` is redacted free text
|
|
7888
|
+
(UNTRUSTED-for-display).
|
|
7889
|
+
additionalProperties: false
|
|
7890
|
+
required: [type, runId, status, summary]
|
|
7891
|
+
properties:
|
|
7892
|
+
type: { const: workflow_complete }
|
|
7893
|
+
runId: { type: string }
|
|
7894
|
+
status: { type: string }
|
|
7895
|
+
summary: { type: string }
|
|
7896
|
+
|
|
7627
7897
|
# ── resources/*.ts schema backfill, batch 2 (2026-07-28) — the 28-item WIRE_PENDING ratchet zeroed.
|
|
7628
7898
|
# Each schema below is cross-checked against the server source (file:line cited in its description
|
|
7629
7899
|
# or in the SDK resource JSDoc it mirrors). Wire objects are OPEN sets (additionalProperties: true).
|
|
@@ -7944,6 +8214,40 @@ components:
|
|
|
7944
8214
|
taskId: { type: string, description: 'Issuing task, when recorded. Additive / tolerate-absent.' }
|
|
7945
8215
|
sessionId: { type: string, description: 'Issuing session, when recorded. Additive / tolerate-absent.' }
|
|
7946
8216
|
|
|
8217
|
+
SteerPriority:
|
|
8218
|
+
type: string
|
|
8219
|
+
enum: [now, next, later]
|
|
8220
|
+
description: >-
|
|
8221
|
+
[2400] TR-4 — per-message queue priority on POST /v1/runs/{taskId}/steer. ACCEPTED + ENUM-VALIDATED
|
|
8222
|
+
FAIL-LOUD (`routes/runs.ts:603`; anything else is 400 `request.field_invalid`) and echoed back on the
|
|
8223
|
+
receipt, but ADVISORY today: core's steer is a single-slot last-writer-wins with no per-message priority
|
|
8224
|
+
or addressable drop, so a faithful priority queue (and DELETE /v1/runs/{taskId}/queue/{messageId}) waits
|
|
8225
|
+
on a core seam.
|
|
8226
|
+
|
|
8227
|
+
SteerReceipt:
|
|
8228
|
+
type: object
|
|
8229
|
+
description: >
|
|
8230
|
+
[2400] TR-4 — the POST /v1/runs/{taskId}/steer receipt, DISCRIMINATED on `delivery` (three server mint
|
|
8231
|
+
points meaning three different things; branch on this, NOT on the status code):
|
|
8232
|
+
`applied` (200, `routes/runs.ts:648`) — injected into the run LIVE on this replica, drains at the next
|
|
8233
|
+
turn boundary (`status:"running"`);
|
|
8234
|
+
`queued` (202, `:641`) — the run is durably SUSPENDED, so the steer was PARKED on its pending checkpoint
|
|
8235
|
+
and is injected on resume (`status:"suspended"`);
|
|
8236
|
+
`parked_for_wake` (202, `:734`) — the run already ENDED; the server minted a `task_done` checkpoint and
|
|
8237
|
+
parked the message on it, delivered ONLY by POST /v1/sessions/{sessionId}/wake — nothing happens until
|
|
8238
|
+
the session is woken.
|
|
8239
|
+
`messageId` is server-minted and stable across all three (dedup / correlation handle).
|
|
8240
|
+
required: [taskId, status, delivery, messageId]
|
|
8241
|
+
# 封闭:三个铸造点是逐字面量拼出来的对象(routes/runs.ts:641/648/734),不是引擎透传形。
|
|
8242
|
+
additionalProperties: false
|
|
8243
|
+
properties:
|
|
8244
|
+
taskId: { type: string }
|
|
8245
|
+
status: { type: string, description: 'The run status the server saw at delivery time (running | suspended | a terminal status).' }
|
|
8246
|
+
delivery: { type: string, enum: [applied, queued, parked_for_wake] }
|
|
8247
|
+
messageId: { type: string, description: 'Server-minted, stable across all three legs.' }
|
|
8248
|
+
priority: { $ref: '#/components/schemas/SteerPriority' }
|
|
8249
|
+
note: { type: string, description: 'Human-readable note on the two parked legs; absent on `applied`.' }
|
|
8250
|
+
|
|
7947
8251
|
SubagentSteerReceipt:
|
|
7948
8252
|
type: object
|
|
7949
8253
|
description: >
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/sdk",
|
|
3
|
-
"version": "4.0
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "Typed, zero-runtime-dependency SDK for the Sema agent fleet usage plane. The shared substrate for all doors (CC/Codex MCP façade + web). Server-side only — tokens never enter the browser.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BUSL-1.1",
|