@sema-agent/sdk 0.0.74 → 0.0.76
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/dist/client.d.ts +48 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +55 -2
- package/dist/client.js.map +1 -1
- package/dist/control-client.d.ts +21 -0
- package/dist/control-client.d.ts.map +1 -1
- package/dist/control-client.js +42 -1
- package/dist/control-client.js.map +1 -1
- package/dist/control-types.d.ts +108 -0
- package/dist/control-types.d.ts.map +1 -1
- package/dist/control-types.js +15 -0
- package/dist/control-types.js.map +1 -1
- package/dist/errors.d.ts +88 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +105 -8
- package/dist/errors.js.map +1 -1
- package/dist/events.d.ts +154 -16
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +1 -0
- package/dist/events.js.map +1 -1
- package/dist/health.d.ts +44 -0
- package/dist/health.d.ts.map +1 -1
- package/dist/health.js +32 -0
- package/dist/health.js.map +1 -1
- package/dist/idempotency.d.ts +8 -0
- package/dist/idempotency.d.ts.map +1 -1
- package/dist/idempotency.js +8 -0
- package/dist/idempotency.js.map +1 -1
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/resources/approvals.d.ts +43 -0
- package/dist/resources/approvals.d.ts.map +1 -1
- package/dist/resources/approvals.js +23 -3
- package/dist/resources/approvals.js.map +1 -1
- package/dist/resources/assistant.d.ts +23 -0
- package/dist/resources/assistant.d.ts.map +1 -1
- package/dist/resources/assistant.js +22 -0
- package/dist/resources/assistant.js.map +1 -1
- package/dist/resources/control/auth-providers.d.ts +17 -0
- package/dist/resources/control/auth-providers.d.ts.map +1 -1
- package/dist/resources/control/auth-providers.js +6 -0
- package/dist/resources/control/auth-providers.js.map +1 -1
- package/dist/resources/control/config.d.ts +22 -0
- package/dist/resources/control/config.d.ts.map +1 -1
- package/dist/resources/control/config.js +12 -0
- package/dist/resources/control/config.js.map +1 -1
- package/dist/resources/control/fleet.d.ts +15 -0
- package/dist/resources/control/fleet.d.ts.map +1 -1
- package/dist/resources/control/fleet.js +8 -0
- package/dist/resources/control/fleet.js.map +1 -1
- package/dist/resources/control/images.d.ts +20 -0
- package/dist/resources/control/images.d.ts.map +1 -1
- package/dist/resources/control/images.js +10 -0
- package/dist/resources/control/images.js.map +1 -1
- package/dist/resources/control/lifecycle.d.ts +8 -0
- package/dist/resources/control/lifecycle.d.ts.map +1 -1
- package/dist/resources/control/lifecycle.js +3 -0
- package/dist/resources/control/lifecycle.js.map +1 -1
- package/dist/resources/control/publish.d.ts +12 -0
- package/dist/resources/control/publish.d.ts.map +1 -1
- package/dist/resources/control/publish.js +6 -0
- package/dist/resources/control/publish.js.map +1 -1
- package/dist/resources/control/secrets.d.ts +28 -0
- package/dist/resources/control/secrets.d.ts.map +1 -1
- package/dist/resources/control/secrets.js +16 -0
- package/dist/resources/control/secrets.js.map +1 -1
- package/dist/resources/control/users.d.ts +22 -0
- package/dist/resources/control/users.d.ts.map +1 -1
- package/dist/resources/control/users.js +12 -0
- package/dist/resources/control/users.js.map +1 -1
- package/dist/resources/control/versioning.d.ts +12 -0
- package/dist/resources/control/versioning.d.ts.map +1 -1
- package/dist/resources/control/versioning.js +6 -0
- package/dist/resources/control/versioning.js.map +1 -1
- package/dist/resources/control/workers.d.ts +14 -0
- package/dist/resources/control/workers.d.ts.map +1 -1
- package/dist/resources/control/workers.js +7 -0
- package/dist/resources/control/workers.js.map +1 -1
- package/dist/resources/elicitations.d.ts +43 -0
- package/dist/resources/elicitations.d.ts.map +1 -1
- package/dist/resources/elicitations.js +8 -0
- package/dist/resources/elicitations.js.map +1 -1
- package/dist/resources/fleet.d.ts +90 -0
- package/dist/resources/fleet.d.ts.map +1 -1
- package/dist/resources/fleet.js +27 -4
- package/dist/resources/fleet.js.map +1 -1
- package/dist/resources/images.d.ts +34 -0
- package/dist/resources/images.d.ts.map +1 -1
- package/dist/resources/images.js +29 -3
- package/dist/resources/images.js.map +1 -1
- package/dist/resources/leader.d.ts +10 -0
- package/dist/resources/leader.d.ts.map +1 -1
- package/dist/resources/leader.js +4 -0
- package/dist/resources/leader.js.map +1 -1
- package/dist/resources/memory.d.ts +37 -0
- package/dist/resources/memory.d.ts.map +1 -1
- package/dist/resources/memory.js +28 -0
- package/dist/resources/memory.js.map +1 -1
- package/dist/resources/models.d.ts +12 -0
- package/dist/resources/models.d.ts.map +1 -1
- package/dist/resources/models.js +4 -0
- package/dist/resources/models.js.map +1 -1
- package/dist/resources/ops.d.ts +16 -0
- package/dist/resources/ops.d.ts.map +1 -1
- package/dist/resources/ops.js +6 -0
- package/dist/resources/ops.js.map +1 -1
- package/dist/resources/policy.d.ts +8 -0
- package/dist/resources/policy.d.ts.map +1 -1
- package/dist/resources/policy.js +1 -0
- package/dist/resources/policy.js.map +1 -1
- package/dist/resources/questions.d.ts +57 -0
- package/dist/resources/questions.d.ts.map +1 -1
- package/dist/resources/questions.js +9 -0
- package/dist/resources/questions.js.map +1 -1
- package/dist/resources/runs.d.ts +143 -0
- package/dist/resources/runs.d.ts.map +1 -1
- package/dist/resources/runs.js +129 -2
- package/dist/resources/runs.js.map +1 -1
- package/dist/resources/session-sync.d.ts +61 -0
- package/dist/resources/session-sync.d.ts.map +1 -1
- package/dist/resources/session-sync.js +54 -1
- package/dist/resources/session-sync.js.map +1 -1
- package/dist/resources/sessions.d.ts +74 -0
- package/dist/resources/sessions.d.ts.map +1 -1
- package/dist/resources/sessions.js +64 -2
- package/dist/resources/sessions.js.map +1 -1
- package/dist/resources/side-query.d.ts +18 -0
- package/dist/resources/side-query.d.ts.map +1 -1
- package/dist/resources/side-query.js +1 -0
- package/dist/resources/side-query.js.map +1 -1
- package/dist/resources/tasks.d.ts +19 -0
- package/dist/resources/tasks.d.ts.map +1 -1
- package/dist/resources/tasks.js +21 -2
- package/dist/resources/tasks.js.map +1 -1
- package/dist/resources/tool-approvals.d.ts +53 -0
- package/dist/resources/tool-approvals.d.ts.map +1 -1
- package/dist/resources/tool-approvals.js +10 -0
- package/dist/resources/tool-approvals.js.map +1 -1
- package/dist/resources/trace.d.ts +23 -0
- package/dist/resources/trace.d.ts.map +1 -1
- package/dist/resources/trace.js +27 -2
- package/dist/resources/trace.js.map +1 -1
- package/dist/resources/usage.d.ts +21 -0
- package/dist/resources/usage.d.ts.map +1 -1
- package/dist/resources/usage.js +8 -0
- package/dist/resources/usage.js.map +1 -1
- package/dist/resources/workflows.d.ts +48 -0
- package/dist/resources/workflows.d.ts.map +1 -1
- package/dist/resources/workflows.js +40 -3
- package/dist/resources/workflows.js.map +1 -1
- package/dist/settings.d.ts +90 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +24 -0
- package/dist/settings.js.map +1 -1
- package/dist/sse.d.ts +36 -0
- package/dist/sse.d.ts.map +1 -1
- package/dist/sse.js +53 -8
- package/dist/sse.js.map +1 -1
- package/dist/sync.d.ts +56 -0
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +48 -4
- package/dist/sync.js.map +1 -1
- package/dist/transport.d.ts +32 -0
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +40 -8
- package/dist/transport.js.map +1 -1
- package/dist/types.d.ts +691 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/resources/runs.js
CHANGED
|
@@ -5,6 +5,12 @@ export class RunsResource {
|
|
|
5
5
|
constructor(t) {
|
|
6
6
|
this.t = t;
|
|
7
7
|
}
|
|
8
|
+
/** server 1.246 ([1499] accept-phase, [1498]⑥ two-拍 rollout) — `?session=` on the legacy run faces.
|
|
9
|
+
* principal answers "whose data"; session answers "which conversation" ([1493]). Pass your conversation's
|
|
10
|
+
* sessionId (the one POST /v1/runs bound) on get/events/cancel/steer/compact/detach and the subagent
|
|
11
|
+
* verbs: today a MISMATCH on a session-bound run 404s (a match/absence passes; absence logs a server-side
|
|
12
|
+
* migration warning), and the enforcement train will 404 absence too — so new code should always send it.
|
|
13
|
+
* NB send a real sessionId or nothing: an EMPTY string counts as present-and-mismatched (404). */
|
|
8
14
|
sessionQs(session) {
|
|
9
15
|
return session !== undefined ? `?session=${encodeURIComponent(session)}` : "";
|
|
10
16
|
}
|
|
@@ -25,6 +31,9 @@ export class RunsResource {
|
|
|
25
31
|
signal: opts?.signal,
|
|
26
32
|
});
|
|
27
33
|
}
|
|
34
|
+
/** Cancel a durable async run (LIVE). 202 ack (`cancelling` or terminal no-op); the run settles
|
|
35
|
+
* to failed+errorCode:"cancelled". 409 = suspended (cancel by DENYING its approval instead); 404 = non-owner/
|
|
36
|
+
* unknown (no existence leak). Server-side idempotent; not a submit → no SDK retry. */
|
|
28
37
|
async cancel(taskId, opts) {
|
|
29
38
|
return this.t.request({
|
|
30
39
|
method: "POST",
|
|
@@ -32,6 +41,13 @@ export class RunsResource {
|
|
|
32
41
|
signal: opts?.signal,
|
|
33
42
|
});
|
|
34
43
|
}
|
|
44
|
+
/** core 1.207 / server 1.78 — DETACH an in-flight tool call (the CC ctrl+b tool-level semantic): the engine
|
|
45
|
+
* adopts the RUNNING process into a background task (spool pre-filled with captured output), the tool call
|
|
46
|
+
* returns early with `Command moved to background; task_id=b*…` (+ `tool_end.structured
|
|
47
|
+
* {type:"bash", detached:true, task_id}`), and the run's turn continues. Fire-and-forget create-then-abort
|
|
48
|
+
* semantics: early/late requests are safe (after completion = no-op). 202 = accepted; 409
|
|
49
|
+
* `detach.not_running` = no such in-flight call; 404 = non-owner/unknown (no existence leak).
|
|
50
|
+
* Works on the sync interactive leg too (server 1.78 registers the live handle). `toolCallId` <= 256 chars. */
|
|
35
51
|
async detach(taskId, toolCallId, opts) {
|
|
36
52
|
return this.t.request({
|
|
37
53
|
method: "POST",
|
|
@@ -40,14 +56,37 @@ export class RunsResource {
|
|
|
40
56
|
signal: opts?.signal,
|
|
41
57
|
});
|
|
42
58
|
}
|
|
59
|
+
/** K-1c (core 1.156 `TaskStream.compact()` / server 1.214 server.js:1596) — MANUAL COMPACT a RUNNING durable
|
|
60
|
+
* run (the CC `/compact` semantic): the engine summarizes the context at the next turn boundary; if anything
|
|
61
|
+
* was summarized a `compacted{trigger:"manual"}` event rides the run's event stream. `instructions` (≤2048
|
|
62
|
+
* code points, non-empty when present — else 400) focuses the summary ("keep the file list", CC parity).
|
|
63
|
+
*
|
|
64
|
+
* Fire-and-forget acceptance: 202 {@link CompactAck} means QUEUED, not compacted — the outcome arrives (or
|
|
65
|
+
* doesn't: mooted/failed compactions emit NO event) on the stream. 🔴 REPLICA-LOCAL like steer/detach:
|
|
66
|
+
* 409 `compact.not_running` = the run settled OR lives on another replica; 501 = no run store (gate on
|
|
67
|
+
* `capabilities.manualCompact`, don't trial-by-501); 404 = non-owner/unknown (no existence leak).
|
|
68
|
+
* Not a submit / server treats repeat calls as fresh asks → NO SDK retry. */
|
|
43
69
|
async compact(taskId, opts) {
|
|
44
70
|
return this.t.request({
|
|
45
71
|
method: "POST",
|
|
72
|
+
// 🔴 body is ALWAYS an object: the server readJson + "body must be a JSON object when present" 400s a
|
|
73
|
+
// bodyless POST on some proxies — `{}` is the no-instructions form (server reads only `instructions`).
|
|
46
74
|
path: `/v1/runs/${encodeURIComponent(taskId)}/compact${this.sessionQs(opts?.session)}`,
|
|
47
75
|
body: opts?.instructions !== undefined ? { instructions: opts.instructions } : {},
|
|
48
76
|
signal: opts?.signal,
|
|
49
77
|
});
|
|
50
78
|
}
|
|
79
|
+
/** design/80 D-A — STEER a RUNNING durable run: inject mid-flight direction (the core of *supervision* vs mere
|
|
80
|
+
* approve/deny). AT-MOST-ONCE — steer is NOT idempotent, so NO submit/retry. `trusted` is NOT a body field:
|
|
81
|
+
* the server derives it from the authenticated operator (the BFF's operator role), never a client-set flag.
|
|
82
|
+
* 🔴 STEER ITSELF IS LIVE/SHIPPED (service §K-6, runStore-gated): 200 = injected into the live run;
|
|
83
|
+
* 202 = PARKED on a checkpoint (delivered when the run next runs); a durable-`suspended` run → typed
|
|
84
|
+
* `SteeringNotRunningError` (`steering.not_running`, 409); a trusted text carrying a control-plane escape →
|
|
85
|
+
* `SteeringInvalidContentError` (`steering.invalid_content`, 422). 🔴 ONE narrow caveat (NOT "steer is a draft"):
|
|
86
|
+
* the per-call `mode` arg is currently a NO-OP — core's steer is HARNESS-LEVEL (`setSteeringMode`), set globally
|
|
87
|
+
* on the runner, not switched per steer call; the `mode` mapping is pending D-A core (search [76]). Sending `mode`
|
|
88
|
+
* is harmless (ignored); steer delivery itself works today. `mode` semantics (when wired): "all" = drain ALL
|
|
89
|
+
* queued steers at the next turn boundary; "one-at-a-time" (default) = one per turn, FIFO. */
|
|
51
90
|
async steer(taskId, steer, opts) {
|
|
52
91
|
return this.t.request({
|
|
53
92
|
method: "POST",
|
|
@@ -56,6 +95,14 @@ export class RunsResource {
|
|
|
56
95
|
signal: opts?.signal,
|
|
57
96
|
});
|
|
58
97
|
}
|
|
98
|
+
/** core 1.219 C2 / server 1.89 — STEER a RUNNING SUBAGENT of this run (the CC "enter the agent's view and
|
|
99
|
+
* type to it" semantic, `AGe` pendingMessages: the message drains at the subagent's NEXT TOOL ROUND).
|
|
100
|
+
* `target` = the delegating tool call's id (`parentToolCallId`, stamped on every forwarded subagent
|
|
101
|
+
* content event) or the agentName (ambiguous name → 409). 🔴 BODY SHAPE differs from the main-run steer:
|
|
102
|
+
* `{ content }` (server SubagentSteerRegistry contract), NOT `{ text }`. Receipt: 200 with
|
|
103
|
+
* `{ taskId, target, status, delivery, note }` — `note` carries the CC-verbatim
|
|
104
|
+
* "Message queued for delivery to <name> at its next tool round."; a settled/unknown subagent →
|
|
105
|
+
* `steering.not_running` 409 (same typed error family as the main-run verb). AT-MOST-ONCE (no retry). */
|
|
59
106
|
async steerSubagent(taskId, target, steer, opts) {
|
|
60
107
|
return this.t.request({
|
|
61
108
|
method: "POST",
|
|
@@ -64,6 +111,19 @@ export class RunsResource {
|
|
|
64
111
|
signal: opts?.signal,
|
|
65
112
|
});
|
|
66
113
|
}
|
|
114
|
+
/** server 1.214 (server.js:1774 subagent-verb region, `verb === "resume"` arm) — RESUME/REVIVE a SETTLED
|
|
115
|
+
* subagent of this run with a follow-up message (the CC "keep talking to the finished agent" semantic):
|
|
116
|
+
* the engine re-opens the subagent's retained session in the background and delivers `content` as its next
|
|
117
|
+
* user turn. Same addressing as {@link steerSubagent} (`target` = parentToolCallId or agentName; ambiguous
|
|
118
|
+
* name → 409 `steering.ambiguous_target`), same `{ content }` body (non-empty, else 400), same
|
|
119
|
+
* {@link SubagentSteerReceipt} 200 (note = "Message queued for delivery to <name>; it will continue in the
|
|
120
|
+
* background.", + `marker`).
|
|
121
|
+
*
|
|
122
|
+
* 🔴 Requires the PARENT run to have retained subagent sessions — the typed-409 family tells you why not:
|
|
123
|
+
* `resume.retain_off` (run didn't set retainSubagentSessions) / `resume.evicted` / `resume.cap` /
|
|
124
|
+
* `resume.session_not_found` (retention lapsed) / `steering.still_running` (it's in flight — STEER instead)
|
|
125
|
+
* / `steering.not_running` (no match on this replica / run settled). Gate on `capabilities.subagentResume`.
|
|
126
|
+
* 404 = non-owner/unknown run (no existence leak). AT-MOST-ONCE (no retry). */
|
|
67
127
|
async resumeSubagent(taskId, target, message, opts) {
|
|
68
128
|
return this.t.request({
|
|
69
129
|
method: "POST",
|
|
@@ -72,6 +132,23 @@ export class RunsResource {
|
|
|
72
132
|
signal: opts?.signal,
|
|
73
133
|
});
|
|
74
134
|
}
|
|
135
|
+
/** server 1.244 ([1488]③b) — read a BACKGROUND child's final report / current status. `target` = the
|
|
136
|
+
* agent handle (a… domain, `background_agent` ONLY — wa… workflow-agent observation rows read via the
|
|
137
|
+
* workflow journal face, and other task kinds 404 here) from the parent's spawn (bg children are NEVER
|
|
138
|
+
* in the run store — GET /v1/runs/:handle 404s
|
|
139
|
+
* with guidance; THIS verb is the read face: the engine TaskRegistry's TaskOutput-tool projection over HTTP).
|
|
140
|
+
* 200 `{ taskId, target, content, output }`: `content` = the TaskOutput text (the child's final assistant
|
|
141
|
+
* body once terminal; honest status text while running), `output` = the registry's UnifiedTaskOutput
|
|
142
|
+
* (status/retrieval_status/partial flags verbatim). Non-blocking (no long-poll). server 1.250: no longer
|
|
143
|
+
* replica-local — a full in-process miss falls back to the durable agent record (cross-instance /
|
|
144
|
+
* post-restart): terminal = final snapshot served, still-running-elsewhere = honest "outcome unknown
|
|
145
|
+
* here". 404 = unknown run / non-owner / unknown handle / no durable row (one indistinguishable arm, no oracle).
|
|
146
|
+
*
|
|
147
|
+
* 🔴 server 1.245 [1493]: this is a CONVERSATION-CONTENT read, so it is SESSION-scoped, not just
|
|
148
|
+
* principal-scoped — pass `session` (your own conversation's sessionId, the one POST /v1/runs returned). A
|
|
149
|
+
* session-bound run served to a caller that omits or mismatches the session → 404 (fail-closed): a sibling
|
|
150
|
+
* session sharing your principal must not read another conversation's child. (Operators/trace bypass.)
|
|
151
|
+
* Gate on `capabilities.subagentOutput`. */
|
|
75
152
|
async subagentOutput(taskId, target, opts) {
|
|
76
153
|
const qs = opts?.session !== undefined ? `?session=${encodeURIComponent(opts.session)}` : "";
|
|
77
154
|
return this.t.request({
|
|
@@ -80,6 +157,23 @@ export class RunsResource {
|
|
|
80
157
|
signal: opts?.signal,
|
|
81
158
|
});
|
|
82
159
|
}
|
|
160
|
+
/** server 1.246 ([1499]) — the GENERIC background task-handle read (CC TaskOutput 对位): serves
|
|
161
|
+
* background_bash (stdout — whether a read consumes the output cursor depends on the handle's shape:
|
|
162
|
+
* spooled handles re-read in full, cursor-only handles return only new bytes; trust the projection's own
|
|
163
|
+
* flags), monitor (batches), and background_agent (final report). A workflow handle 404s (its read face is
|
|
164
|
+
* the workflow journal). 🔴 `target` is the CANONICAL task handle only (b…/m…/a… task_id from the spawn) —
|
|
165
|
+
* the in-engine tools' agent-name / legacy-id resolution is NOT on the wire (404). 🔴 NO server-side
|
|
166
|
+
* filter: `?filter=` is REFUSED with 400 on both verbs (wire-supplied regexes don't run on the server) —
|
|
167
|
+
* fetch the output and apply your regex locally, knowing the wire serves the CLIPPED projection (matches
|
|
168
|
+
* inside a clipped middle are not recoverable, and a cursor-only bash leg consumes what it serves; the
|
|
169
|
+
* in-engine tool filters before clipping and keeps full fidelity). SESSION-
|
|
170
|
+
* scoped like {@link subagentOutput} — pass your conversation's `session`; a session-bound run without/with
|
|
171
|
+
* a mismatched one → 404 fail-closed (operators bypass). Non-blocking. server 1.250: an `a*` handle is
|
|
172
|
+
* no longer replica-local — a full in-process miss falls back to the durable record (cross-instance /
|
|
173
|
+
* post-restart): terminal rows serve the final snapshot, a row still running on another replica answers
|
|
174
|
+
* an honest "outcome unknown here" (never fabricated liveness). `b*`/`m*` handles stay replica-local
|
|
175
|
+
* (no durable face). Gate on
|
|
176
|
+
* `capabilities.taskHandles`. */
|
|
83
177
|
async taskOutput(taskId, target, opts) {
|
|
84
178
|
return this.t.request({
|
|
85
179
|
method: "GET",
|
|
@@ -87,6 +181,16 @@ export class RunsResource {
|
|
|
87
181
|
signal: opts?.signal,
|
|
88
182
|
});
|
|
89
183
|
}
|
|
184
|
+
/** server 1.246 ([1499]) — stop a background task handle (CC TaskStop 对位): bash kill / monitor stop /
|
|
185
|
+
* agent abort, attributed "user" (`output.stoppedBy`). Idempotent on a terminal handle — the 200
|
|
186
|
+
* `output.status` tells you what actually happened. 🔴 A kill that does NOT land is a 409
|
|
187
|
+
* `stop.not_landed` (body carries the honest projection: `output.status` stays "running") — never a 200;
|
|
188
|
+
* treat only 200 as stopped. server 1.250 durable arm: an `a*` handle NOT attached to this replica
|
|
189
|
+
* (cross-instance / post-restart) answers from the durable record — terminal row = 200 already-terminal
|
|
190
|
+
* (idempotent-honest), still-running-elsewhere = 409 `stop.not_local` (no kill was attempted; distinct
|
|
191
|
+
* from not_landed). Same session scoping + kind set + canonical-handle
|
|
192
|
+
* addressing as {@link taskOutput} (a workflow handle 404s — stop workflows via their cancel face). Gate
|
|
193
|
+
* on `capabilities.taskHandles`. */
|
|
90
194
|
async taskStop(taskId, target, opts) {
|
|
91
195
|
return this.t.request({
|
|
92
196
|
method: "POST",
|
|
@@ -94,6 +198,26 @@ export class RunsResource {
|
|
|
94
198
|
signal: opts?.signal,
|
|
95
199
|
});
|
|
96
200
|
}
|
|
201
|
+
/** server 1.251(S2,core 1.370 `bgAgentId`)— a background child's per-agent **live tail** (SSE):
|
|
202
|
+
* `GET /v1/runs/:id/subagents/:handle/stream`. The "tail" half of replay+tail — {@link subagentOutput}
|
|
203
|
+
* (+AgentTranscript in-engine) is the replay half. Frames: `meta` (once — carries `status` and
|
|
204
|
+
* `live:"replica-local"`; on a TERMINAL child the stream ends right after it, go read the replay face),
|
|
205
|
+
* `forward` (content: text_delta / reasoning_delta / tool_start / tool_end / task_progress — same
|
|
206
|
+
* projection discipline as the main run stream's forward branch, plus a bus-level
|
|
207
|
+
* `{type:"lagged",dropped}` marker when a slow consumer dropped frames — honest, never silent), and
|
|
208
|
+
* `heartbeat` (ignore), and `{type:"task_settled",status,seq?}` — the child settled MID-stream (the server
|
|
209
|
+
* writes it and ends the stream; the full story continues on the replay face). Live frames are REPLICA-LOCAL (produced only where the host run executes) — a
|
|
210
|
+
* child running on another replica yields heartbeats only. Same addressing/gates/404-shape as
|
|
211
|
+
* {@link subagentOutput} (session-enforced). Stop-cycle `seq` (server 1.255 + core 1.373): the
|
|
212
|
+
* `task_settled` frame carries the settle-minted generation number (1 = first settle; ≥2 = a revived
|
|
213
|
+
* child settling again) — the real-time revive discriminator. The `meta` frame's optional `seq` appears
|
|
214
|
+
* ONLY when the probe served a terminal durable row cross-instance/post-restart (in-process polls do not
|
|
215
|
+
* project it — its absence does NOT mean "never settled"). Consumption notes (server 1.253): after a `task_settled`
|
|
216
|
+
* close, a REVIVED child (stop-cycle seq≥2) = open a NEW stream; after a `lagged` marker the dropped
|
|
217
|
+
* frames are NOT recoverable on this lane — rebuild from the replay face, then re-tail. NESTED bg
|
|
218
|
+
* children's frames merge into the OUTERMOST handle's stream (core overwrites bgAgentId per bg boundary;
|
|
219
|
+
* discriminate nested frames by parentToolCallId) — a nested handle's own stream carries meta+heartbeat
|
|
220
|
+
* only. Gate on `capabilities.subagentStream`. */
|
|
97
221
|
async *subagentStream(taskId, target, opts) {
|
|
98
222
|
const o = {
|
|
99
223
|
method: "GET",
|
|
@@ -107,14 +231,17 @@ export class RunsResource {
|
|
|
107
231
|
try {
|
|
108
232
|
for await (const frame of readSseFrames(res, undefined, opts?.signal)) {
|
|
109
233
|
if (!frame.data)
|
|
110
|
-
continue;
|
|
234
|
+
continue; // comment-only frames (heartbeat carries data:{} and IS yielded)
|
|
111
235
|
yield { event: frame.event ?? "message", data: JSON.parse(frame.data) };
|
|
112
236
|
}
|
|
113
237
|
}
|
|
114
238
|
finally {
|
|
115
|
-
res.body?.cancel().catch(() => { });
|
|
239
|
+
res.body?.cancel().catch(() => { }); // disconnect = server clears the in-process tail subscription
|
|
116
240
|
}
|
|
117
241
|
}
|
|
242
|
+
/** Resumable event stream. Internally: SSE + Last-Event-ID auto-reconnect; on a 416 (evicted past retention,
|
|
243
|
+
* body `{error,retainedFrom}` — match status, no RESUME_EVICTED code) → full-sync via trace.turns then resume
|
|
244
|
+
* from `retainedFrom` (sse.ts). Established-stream drops do NOT count as retries. */
|
|
118
245
|
async *events(taskId, opts) {
|
|
119
246
|
let first = opts?.lastEventId;
|
|
120
247
|
yield* parseSse((lastEventId) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runs.js","sourceRoot":"","sources":["../../src/resources/runs.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAwD1C,MAAM,OAAO,YAAY;IACM;IAA7B,YAA6B,CAAY;QAAZ,MAAC,GAAD,CAAC,CAAW;IAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"runs.js","sourceRoot":"","sources":["../../src/resources/runs.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,27 +1,80 @@
|
|
|
1
|
+
/** 2c session-sync (P1d) — the SDK as the LOCAL peer's client of the cloud's `/v1/sessions/:id/sync/*` routes
|
|
2
|
+
* (service src/http/server.ts:2825-3172). The real topology is TWO PROCESSES (the local shell's local
|
|
3
|
+
* backend + this cloud service); these methods let the local peer PULL a session's whole state out of the cloud
|
|
4
|
+
* or PUSH its own in. The whole surface is gated off `capabilities().sessionSync` (= durable backend + entry
|
|
5
|
+
* export + a file-snapshot store wired) — DON'T trial-by-501.
|
|
6
|
+
*
|
|
7
|
+
* PULL (read the cloud): manifest() → entries() (NDJSON) → getBlob() for the hashes the local peer lacks.
|
|
8
|
+
* PUSH (write the cloud): putBlob() the blobs the cloud lacks → import() Phase A → importEntries() Phase B.
|
|
9
|
+
* PLAN (dry run): plan() classifies what a PUSH WOULD do, no write.
|
|
10
|
+
*
|
|
11
|
+
* Owner-gated exactly like fork/delete (§9): a PULL 404s a non-owner (no existence oracle); a PUSH is own-or-FRESH
|
|
12
|
+
* (a session that does not exist yet, the caller is about to import it, is allowed). A non-uuidv7 id → 400. A
|
|
13
|
+
* PUSH/PLAN that would lose dst history (fork/stale) without `resolution:"overwrite-dst"` → a typed
|
|
14
|
+
* {@link import("../errors.js").SyncConflictError} (409). */
|
|
1
15
|
import type { Transport } from "../transport.js";
|
|
2
16
|
import type { SessionManifest, SyncEntry, SyncSnapshot, SessionRulesRecord, SyncAnchor, SyncRelation, ImportStaged, ImportCommitted } from "../types.js";
|
|
3
17
|
export declare class SessionSyncResource {
|
|
4
18
|
private readonly t;
|
|
5
19
|
constructor(t: Transport);
|
|
20
|
+
/** PULL — `GET …/sync/manifest` → the THIN cross-backend snapshot (entry IDS + per-snapshot relPath→blobHash +
|
|
21
|
+
* policy + anchors + leaf), NO entry payloads and NO blob bytes (those stream / are content-addressed). The
|
|
22
|
+
* server wraps it as `{ manifest }`; this unwraps to the bare {@link SessionManifest}. Feed `manifest.entryIds`
|
|
23
|
+
* to `classifySyncRelationshipByIds` to decide fast-forward/fork BEFORE pulling the entry stream + only the
|
|
24
|
+
* blob hashes the local peer lacks. Owner-scoped (non-owner → 404, no oracle); 400 on a non-uuidv7 id; 501
|
|
25
|
+
* without a durable session store. */
|
|
6
26
|
manifest(sessionId: string, opts?: {
|
|
7
27
|
signal?: AbortSignal;
|
|
8
28
|
}): Promise<SessionManifest>;
|
|
29
|
+
/** PULL — `GET …/sync/entries[?afterSeq=N]` → the entry PAYLOADS as an NDJSON stream (one JSON entry per line,
|
|
30
|
+
* begin/end-sentinel framed). Yields each entry verbatim (opaque to the SDK — the cloud re-validates the tree).
|
|
31
|
+
* 🔴 The stream's status is committed at 200 BEFORE the first line, so a mid-stream failure ends the body
|
|
32
|
+
* WITHOUT the `{"__sync":"end",count}` trailer — `parseNdjsonEntries` throws `SyncTruncatedError` on a missing
|
|
33
|
+
* trailer or a count mismatch (the SOLE truncation signal; there is no 5xx mid-stream). `afterSeq` is a resume
|
|
34
|
+
* cursor = the backend-native durable `seq` (yield seq>afterSeq); resume is SAME-BACKEND only. A non-200
|
|
35
|
+
* (404 raced delete / 501 / 400) surfaces as a typed APIError BEFORE any entry is yielded. */
|
|
9
36
|
entries(sessionId: string, params?: {
|
|
10
37
|
afterSeq?: number;
|
|
11
38
|
}, opts?: {
|
|
12
39
|
signal?: AbortSignal;
|
|
13
40
|
}): AsyncGenerator<SyncEntry>;
|
|
41
|
+
/** PULL one content-addressed blob's RAW bytes — `GET …/sync/snapshots/:key/blobs/:hash` (NOTE the PULL path is
|
|
42
|
+
* scoped under the snapshot `:key`, NOT the bare `blobs/:hash` of the PUSH). The scope check is the security
|
|
43
|
+
* boundary: a content-addressed blob is shared across sessions, so the cloud only serves a hash THIS session's
|
|
44
|
+
* `:key` manifest references (a foreign/unreferenced hash → 404 `blob not found`). The SDK validates the hash
|
|
45
|
+
* shape locally (400 `blob hash must be 64 lowercase-hex chars`). Returns the bytes as a `Uint8Array`. */
|
|
14
46
|
getBlob(sessionId: string, key: string, hash: string, opts?: {
|
|
15
47
|
signal?: AbortSignal;
|
|
16
48
|
}): Promise<Uint8Array>;
|
|
49
|
+
/** PUSH one content-addressed blob INTO the cloud's snapshot store — `PUT …/sync/blobs/:hash` (the bare path; the
|
|
50
|
+
* PULL is scoped under `snapshots/:key`). RAW bytes body, octet-stream. The cloud verifies sha256(body)===:hash
|
|
51
|
+
* (the content-address integrity guard) — a mismatch → 400 `blob hash mismatch`; the SDK validates the hash
|
|
52
|
+
* shape locally first. own-or-FRESH gate. Per-blob cap = 64 MiB (the cloud 413s mid-stream beyond it). A backend
|
|
53
|
+
* write failure (e.g. a MinIO non-2xx) → 502 `blob store write failed` (RETRYABLE — the transport retries 502 on
|
|
54
|
+
* a... no: openRaw does NOT retry, the caller re-PUTs; the blob is content-addressed-idempotent). 204 on success
|
|
55
|
+
* (no body). Call this for every blob hash the manifest references that the cloud lacks BEFORE import Phase A. */
|
|
17
56
|
putBlob(sessionId: string, hash: string, bytes: Uint8Array, opts?: {
|
|
18
57
|
signal?: AbortSignal;
|
|
19
58
|
}): Promise<void>;
|
|
59
|
+
/** PLAN (dry-run) — `POST …/sync/plan` body `{ entryIds }` (the LOCAL peer's entry-id list, oldest-first) →
|
|
60
|
+
* classify what a PUSH WOULD do against the cloud's current log, WITHOUT writing. Returns the §7 {@link SyncRelation}
|
|
61
|
+
* (`fresh` for a fresh cloud session). own-or-FRESH gate; 400 on a non-string-array body / a non-uuidv7 id.
|
|
62
|
+
* NB: unlike import, plan never 409s — it is a pure read-side classify (a fork/stale is REPORTED in the relation,
|
|
63
|
+
* not raised). Use it to surface the keep-local/keep-cloud divergence before committing to a PUSH. */
|
|
20
64
|
plan(sessionId: string, body: {
|
|
21
65
|
entryIds: string[];
|
|
22
66
|
}, opts?: {
|
|
23
67
|
signal?: AbortSignal;
|
|
24
68
|
}): Promise<SyncRelation>;
|
|
69
|
+
/** PUSH Phase A — `POST …/sync/import` body `{ entryIds, snapshots, policy, anchors, resolution? }` (the SMALL
|
|
70
|
+
* metadata; entries stream in Phase B). The cloud classifies (§7), pre-checks blob presence (every referenced
|
|
71
|
+
* hash must have been PUT — a missing one → 422 `missing_blob`), guards the import lease + any active run (409),
|
|
72
|
+
* then mints a stagingId. Returns {@link ImportStaged}:
|
|
73
|
+
* - `identical` → `{ relation:"identical" }` with NO `stagingId` (the dst already holds the log; skip Phase B).
|
|
74
|
+
* - `fresh`/`fast_forward` → `{ stagingId, relation }` — drive Phase B with the `stagingId`.
|
|
75
|
+
* 🔴 a `fork`/`stale` WITHOUT `resolution:"overwrite-dst"` → a typed SyncConflictError (409, carrying the relation).
|
|
76
|
+
* An active run on the session → ConflictError (409, `session_active`, `activeTaskId`); an in-flight import →
|
|
77
|
+
* ConflictError (409, `import_in_flight`). Not a submit (it mints a distinct staging token) → no SDK retry. */
|
|
25
78
|
import(sessionId: string, body: {
|
|
26
79
|
entryIds: string[];
|
|
27
80
|
snapshots: SyncSnapshot[];
|
|
@@ -31,6 +84,14 @@ export declare class SessionSyncResource {
|
|
|
31
84
|
}, opts?: {
|
|
32
85
|
signal?: AbortSignal;
|
|
33
86
|
}): Promise<ImportStaged>;
|
|
87
|
+
/** PUSH Phase B — `POST …/sync/import/:stagingId/entries`: stream the entry log as an NDJSON REQUEST body into the
|
|
88
|
+
* staged shadow id, then the cloud `finish()`-validates (exactly-one-root + leaf-resolvable) → commits (the atomic
|
|
89
|
+
* swap) → replays snapshots/policy/anchors. Returns {@link ImportCommitted} (`{ relation }`, the AUTHORITATIVE
|
|
90
|
+
* in-txn re-classify). The SDK serializes the entries to NDJSON (one JSON per line) and sends them as the raw body
|
|
91
|
+
* (NOT JSON.stringify of an array — the cloud line-buffers). Re-POSTing the same stagingId is idempotent
|
|
92
|
+
* (appendBatch dedups; the commit re-runs). Typed errors: a per-entry/structural violation → 422 `invalid_entries`;
|
|
93
|
+
* a line too large → 413; a commit-time TOCTOU flip to fork/stale → a typed SyncConflictError (409); a refused
|
|
94
|
+
* policy loosen → 403 `loosen_forbidden`; a wrong/foreign stagingId → 404. */
|
|
34
95
|
importEntries(sessionId: string, stagingId: string, entries: Iterable<SyncEntry> | AsyncIterable<SyncEntry>, opts?: {
|
|
35
96
|
signal?: AbortSignal;
|
|
36
97
|
}): Promise<ImportCommitted>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-sync.d.ts","sourceRoot":"","sources":["../../src/resources/session-sync.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"session-sync.d.ts","sourceRoot":"","sources":["../../src/resources/session-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;8DAa8D;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,OAAO,KAAK,EACV,eAAe,EACf,SAAS,EACT,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EAChB,MAAM,aAAa,CAAC;AAMrB,qBAAa,mBAAmB;IAClB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,SAAS;IAEzC;;;;;2CAKuC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,eAAe,CAAC;IAS5F;;;;;;mGAM+F;IACxF,OAAO,CACZ,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,EAC9B,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAC9B,cAAc,CAAC,SAAS,CAAC;IAQ5B;;;;+GAI2G;IACrG,OAAO,CACX,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAC9B,OAAO,CAAC,UAAU,CAAC;IAYtB;;;;;;uHAMmH;IAC7G,OAAO,CACX,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,UAAU,EACjB,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAC9B,OAAO,CAAC,IAAI,CAAC;IAahB;;;;2GAIuG;IACjG,IAAI,CACR,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,EAC5B,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAC9B,OAAO,CAAC,YAAY,CAAC;IASxB;;;;;;;;oHAQgH;IAC1G,MAAM,CACV,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;QACJ,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,SAAS,EAAE,YAAY,EAAE,CAAC;QAC1B,MAAM,EAAE,kBAAkB,EAAE,CAAC;QAC7B,OAAO,EAAE,UAAU,EAAE,CAAC;QACtB,UAAU,CAAC,EAAE,eAAe,CAAC;KAC9B,EACD,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAC9B,OAAO,CAAC,YAAY,CAAC;IASxB;;;;;;;mFAO+E;IACzE,aAAa,CACjB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,GAAG,aAAa,CAAC,SAAS,CAAC,EACvD,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAC9B,OAAO,CAAC,eAAe,CAAC;CAY5B"}
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import { toApiError } from "../errors.js";
|
|
2
2
|
import { parseNdjsonEntries } from "../sse.js";
|
|
3
|
+
/** A 64-lowercase-hex SHA-256 — the content-address the cloud asserts on a blob GET/PUT (server.ts SHA256_HEX_RE).
|
|
4
|
+
* The SDK validates the shape locally so a malformed hash fails fast (the cloud also 400s it). */
|
|
3
5
|
const SHA256_HEX_RE = /^[0-9a-f]{64}$/;
|
|
4
6
|
export class SessionSyncResource {
|
|
5
7
|
t;
|
|
6
8
|
constructor(t) {
|
|
7
9
|
this.t = t;
|
|
8
10
|
}
|
|
11
|
+
/** PULL — `GET …/sync/manifest` → the THIN cross-backend snapshot (entry IDS + per-snapshot relPath→blobHash +
|
|
12
|
+
* policy + anchors + leaf), NO entry payloads and NO blob bytes (those stream / are content-addressed). The
|
|
13
|
+
* server wraps it as `{ manifest }`; this unwraps to the bare {@link SessionManifest}. Feed `manifest.entryIds`
|
|
14
|
+
* to `classifySyncRelationshipByIds` to decide fast-forward/fork BEFORE pulling the entry stream + only the
|
|
15
|
+
* blob hashes the local peer lacks. Owner-scoped (non-owner → 404, no oracle); 400 on a non-uuidv7 id; 501
|
|
16
|
+
* without a durable session store. */
|
|
9
17
|
async manifest(sessionId, opts) {
|
|
10
18
|
const out = await this.t.request({
|
|
11
19
|
method: "GET",
|
|
@@ -14,6 +22,13 @@ export class SessionSyncResource {
|
|
|
14
22
|
});
|
|
15
23
|
return out.manifest;
|
|
16
24
|
}
|
|
25
|
+
/** PULL — `GET …/sync/entries[?afterSeq=N]` → the entry PAYLOADS as an NDJSON stream (one JSON entry per line,
|
|
26
|
+
* begin/end-sentinel framed). Yields each entry verbatim (opaque to the SDK — the cloud re-validates the tree).
|
|
27
|
+
* 🔴 The stream's status is committed at 200 BEFORE the first line, so a mid-stream failure ends the body
|
|
28
|
+
* WITHOUT the `{"__sync":"end",count}` trailer — `parseNdjsonEntries` throws `SyncTruncatedError` on a missing
|
|
29
|
+
* trailer or a count mismatch (the SOLE truncation signal; there is no 5xx mid-stream). `afterSeq` is a resume
|
|
30
|
+
* cursor = the backend-native durable `seq` (yield seq>afterSeq); resume is SAME-BACKEND only. A non-200
|
|
31
|
+
* (404 raced delete / 501 / 400) surfaces as a typed APIError BEFORE any entry is yielded. */
|
|
17
32
|
async *entries(sessionId, params, opts) {
|
|
18
33
|
let path = `/v1/sessions/${encodeURIComponent(sessionId)}/sync/entries`;
|
|
19
34
|
if (params?.afterSeq !== undefined)
|
|
@@ -23,6 +38,11 @@ export class SessionSyncResource {
|
|
|
23
38
|
throw toApiError(res.status, await safeJson(res));
|
|
24
39
|
yield* parseNdjsonEntries(res, opts?.signal);
|
|
25
40
|
}
|
|
41
|
+
/** PULL one content-addressed blob's RAW bytes — `GET …/sync/snapshots/:key/blobs/:hash` (NOTE the PULL path is
|
|
42
|
+
* scoped under the snapshot `:key`, NOT the bare `blobs/:hash` of the PUSH). The scope check is the security
|
|
43
|
+
* boundary: a content-addressed blob is shared across sessions, so the cloud only serves a hash THIS session's
|
|
44
|
+
* `:key` manifest references (a foreign/unreferenced hash → 404 `blob not found`). The SDK validates the hash
|
|
45
|
+
* shape locally (400 `blob hash must be 64 lowercase-hex chars`). Returns the bytes as a `Uint8Array`. */
|
|
26
46
|
async getBlob(sessionId, key, hash, opts) {
|
|
27
47
|
if (!SHA256_HEX_RE.test(hash))
|
|
28
48
|
throw toApiError(400, { error: "blob hash must be 64 lowercase-hex chars" });
|
|
@@ -36,6 +56,13 @@ export class SessionSyncResource {
|
|
|
36
56
|
throw toApiError(res.status, await safeJson(res));
|
|
37
57
|
return new Uint8Array(await res.arrayBuffer());
|
|
38
58
|
}
|
|
59
|
+
/** PUSH one content-addressed blob INTO the cloud's snapshot store — `PUT …/sync/blobs/:hash` (the bare path; the
|
|
60
|
+
* PULL is scoped under `snapshots/:key`). RAW bytes body, octet-stream. The cloud verifies sha256(body)===:hash
|
|
61
|
+
* (the content-address integrity guard) — a mismatch → 400 `blob hash mismatch`; the SDK validates the hash
|
|
62
|
+
* shape locally first. own-or-FRESH gate. Per-blob cap = 64 MiB (the cloud 413s mid-stream beyond it). A backend
|
|
63
|
+
* write failure (e.g. a MinIO non-2xx) → 502 `blob store write failed` (RETRYABLE — the transport retries 502 on
|
|
64
|
+
* a... no: openRaw does NOT retry, the caller re-PUTs; the blob is content-addressed-idempotent). 204 on success
|
|
65
|
+
* (no body). Call this for every blob hash the manifest references that the cloud lacks BEFORE import Phase A. */
|
|
39
66
|
async putBlob(sessionId, hash, bytes, opts) {
|
|
40
67
|
if (!SHA256_HEX_RE.test(hash))
|
|
41
68
|
throw toApiError(400, { error: "blob hash must be 64 lowercase-hex chars" });
|
|
@@ -47,8 +74,14 @@ export class SessionSyncResource {
|
|
|
47
74
|
signal: opts?.signal,
|
|
48
75
|
});
|
|
49
76
|
if (!res.ok)
|
|
50
|
-
throw toApiError(res.status, await safeJson(res));
|
|
77
|
+
throw toApiError(res.status, await safeJson(res)); // 400 mismatch / 413 too large / 501 / 502 write-failed
|
|
78
|
+
// 204 No Content — nothing to read.
|
|
51
79
|
}
|
|
80
|
+
/** PLAN (dry-run) — `POST …/sync/plan` body `{ entryIds }` (the LOCAL peer's entry-id list, oldest-first) →
|
|
81
|
+
* classify what a PUSH WOULD do against the cloud's current log, WITHOUT writing. Returns the §7 {@link SyncRelation}
|
|
82
|
+
* (`fresh` for a fresh cloud session). own-or-FRESH gate; 400 on a non-string-array body / a non-uuidv7 id.
|
|
83
|
+
* NB: unlike import, plan never 409s — it is a pure read-side classify (a fork/stale is REPORTED in the relation,
|
|
84
|
+
* not raised). Use it to surface the keep-local/keep-cloud divergence before committing to a PUSH. */
|
|
52
85
|
async plan(sessionId, body, opts) {
|
|
53
86
|
return this.t.request({
|
|
54
87
|
method: "POST",
|
|
@@ -57,6 +90,15 @@ export class SessionSyncResource {
|
|
|
57
90
|
signal: opts?.signal,
|
|
58
91
|
});
|
|
59
92
|
}
|
|
93
|
+
/** PUSH Phase A — `POST …/sync/import` body `{ entryIds, snapshots, policy, anchors, resolution? }` (the SMALL
|
|
94
|
+
* metadata; entries stream in Phase B). The cloud classifies (§7), pre-checks blob presence (every referenced
|
|
95
|
+
* hash must have been PUT — a missing one → 422 `missing_blob`), guards the import lease + any active run (409),
|
|
96
|
+
* then mints a stagingId. Returns {@link ImportStaged}:
|
|
97
|
+
* - `identical` → `{ relation:"identical" }` with NO `stagingId` (the dst already holds the log; skip Phase B).
|
|
98
|
+
* - `fresh`/`fast_forward` → `{ stagingId, relation }` — drive Phase B with the `stagingId`.
|
|
99
|
+
* 🔴 a `fork`/`stale` WITHOUT `resolution:"overwrite-dst"` → a typed SyncConflictError (409, carrying the relation).
|
|
100
|
+
* An active run on the session → ConflictError (409, `session_active`, `activeTaskId`); an in-flight import →
|
|
101
|
+
* ConflictError (409, `import_in_flight`). Not a submit (it mints a distinct staging token) → no SDK retry. */
|
|
60
102
|
async import(sessionId, body, opts) {
|
|
61
103
|
return this.t.request({
|
|
62
104
|
method: "POST",
|
|
@@ -65,6 +107,14 @@ export class SessionSyncResource {
|
|
|
65
107
|
signal: opts?.signal,
|
|
66
108
|
});
|
|
67
109
|
}
|
|
110
|
+
/** PUSH Phase B — `POST …/sync/import/:stagingId/entries`: stream the entry log as an NDJSON REQUEST body into the
|
|
111
|
+
* staged shadow id, then the cloud `finish()`-validates (exactly-one-root + leaf-resolvable) → commits (the atomic
|
|
112
|
+
* swap) → replays snapshots/policy/anchors. Returns {@link ImportCommitted} (`{ relation }`, the AUTHORITATIVE
|
|
113
|
+
* in-txn re-classify). The SDK serializes the entries to NDJSON (one JSON per line) and sends them as the raw body
|
|
114
|
+
* (NOT JSON.stringify of an array — the cloud line-buffers). Re-POSTing the same stagingId is idempotent
|
|
115
|
+
* (appendBatch dedups; the commit re-runs). Typed errors: a per-entry/structural violation → 422 `invalid_entries`;
|
|
116
|
+
* a line too large → 413; a commit-time TOCTOU flip to fork/stale → a typed SyncConflictError (409); a refused
|
|
117
|
+
* policy loosen → 403 `loosen_forbidden`; a wrong/foreign stagingId → 404. */
|
|
68
118
|
async importEntries(sessionId, stagingId, entries, opts) {
|
|
69
119
|
const ndjson = await toNdjson(entries);
|
|
70
120
|
const res = await this.t.openRaw({
|
|
@@ -79,6 +129,9 @@ export class SessionSyncResource {
|
|
|
79
129
|
return (await res.json());
|
|
80
130
|
}
|
|
81
131
|
}
|
|
132
|
+
/** Serialize entries to an NDJSON body (one JSON value per `\n`-terminated line) for the Phase-B stream. Accepts a
|
|
133
|
+
* sync or async iterable so the caller can pipe a `PULL …/sync/entries` stream straight into a PUSH without
|
|
134
|
+
* materializing the whole log. */
|
|
82
135
|
async function toNdjson(entries) {
|
|
83
136
|
let body = "";
|
|
84
137
|
for await (const e of entries)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-sync.js","sourceRoot":"","sources":["../../src/resources/session-sync.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"session-sync.js","sourceRoot":"","sources":["../../src/resources/session-sync.ts"],"names":[],"mappings":"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"}
|