@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.
Files changed (171) hide show
  1. package/dist/client.d.ts +48 -0
  2. package/dist/client.d.ts.map +1 -1
  3. package/dist/client.js +55 -2
  4. package/dist/client.js.map +1 -1
  5. package/dist/control-client.d.ts +21 -0
  6. package/dist/control-client.d.ts.map +1 -1
  7. package/dist/control-client.js +42 -1
  8. package/dist/control-client.js.map +1 -1
  9. package/dist/control-types.d.ts +108 -0
  10. package/dist/control-types.d.ts.map +1 -1
  11. package/dist/control-types.js +15 -0
  12. package/dist/control-types.js.map +1 -1
  13. package/dist/errors.d.ts +88 -2
  14. package/dist/errors.d.ts.map +1 -1
  15. package/dist/errors.js +105 -8
  16. package/dist/errors.js.map +1 -1
  17. package/dist/events.d.ts +154 -16
  18. package/dist/events.d.ts.map +1 -1
  19. package/dist/events.js +1 -0
  20. package/dist/events.js.map +1 -1
  21. package/dist/health.d.ts +44 -0
  22. package/dist/health.d.ts.map +1 -1
  23. package/dist/health.js +32 -0
  24. package/dist/health.js.map +1 -1
  25. package/dist/idempotency.d.ts +8 -0
  26. package/dist/idempotency.d.ts.map +1 -1
  27. package/dist/idempotency.js +8 -0
  28. package/dist/idempotency.js.map +1 -1
  29. package/dist/index.d.ts +19 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +13 -0
  32. package/dist/index.js.map +1 -1
  33. package/dist/resources/approvals.d.ts +43 -0
  34. package/dist/resources/approvals.d.ts.map +1 -1
  35. package/dist/resources/approvals.js +23 -3
  36. package/dist/resources/approvals.js.map +1 -1
  37. package/dist/resources/assistant.d.ts +23 -0
  38. package/dist/resources/assistant.d.ts.map +1 -1
  39. package/dist/resources/assistant.js +22 -0
  40. package/dist/resources/assistant.js.map +1 -1
  41. package/dist/resources/control/auth-providers.d.ts +17 -0
  42. package/dist/resources/control/auth-providers.d.ts.map +1 -1
  43. package/dist/resources/control/auth-providers.js +6 -0
  44. package/dist/resources/control/auth-providers.js.map +1 -1
  45. package/dist/resources/control/config.d.ts +22 -0
  46. package/dist/resources/control/config.d.ts.map +1 -1
  47. package/dist/resources/control/config.js +12 -0
  48. package/dist/resources/control/config.js.map +1 -1
  49. package/dist/resources/control/fleet.d.ts +15 -0
  50. package/dist/resources/control/fleet.d.ts.map +1 -1
  51. package/dist/resources/control/fleet.js +8 -0
  52. package/dist/resources/control/fleet.js.map +1 -1
  53. package/dist/resources/control/images.d.ts +20 -0
  54. package/dist/resources/control/images.d.ts.map +1 -1
  55. package/dist/resources/control/images.js +10 -0
  56. package/dist/resources/control/images.js.map +1 -1
  57. package/dist/resources/control/lifecycle.d.ts +8 -0
  58. package/dist/resources/control/lifecycle.d.ts.map +1 -1
  59. package/dist/resources/control/lifecycle.js +3 -0
  60. package/dist/resources/control/lifecycle.js.map +1 -1
  61. package/dist/resources/control/publish.d.ts +12 -0
  62. package/dist/resources/control/publish.d.ts.map +1 -1
  63. package/dist/resources/control/publish.js +6 -0
  64. package/dist/resources/control/publish.js.map +1 -1
  65. package/dist/resources/control/secrets.d.ts +28 -0
  66. package/dist/resources/control/secrets.d.ts.map +1 -1
  67. package/dist/resources/control/secrets.js +16 -0
  68. package/dist/resources/control/secrets.js.map +1 -1
  69. package/dist/resources/control/users.d.ts +22 -0
  70. package/dist/resources/control/users.d.ts.map +1 -1
  71. package/dist/resources/control/users.js +12 -0
  72. package/dist/resources/control/users.js.map +1 -1
  73. package/dist/resources/control/versioning.d.ts +12 -0
  74. package/dist/resources/control/versioning.d.ts.map +1 -1
  75. package/dist/resources/control/versioning.js +6 -0
  76. package/dist/resources/control/versioning.js.map +1 -1
  77. package/dist/resources/control/workers.d.ts +14 -0
  78. package/dist/resources/control/workers.d.ts.map +1 -1
  79. package/dist/resources/control/workers.js +7 -0
  80. package/dist/resources/control/workers.js.map +1 -1
  81. package/dist/resources/elicitations.d.ts +43 -0
  82. package/dist/resources/elicitations.d.ts.map +1 -1
  83. package/dist/resources/elicitations.js +8 -0
  84. package/dist/resources/elicitations.js.map +1 -1
  85. package/dist/resources/fleet.d.ts +90 -0
  86. package/dist/resources/fleet.d.ts.map +1 -1
  87. package/dist/resources/fleet.js +27 -4
  88. package/dist/resources/fleet.js.map +1 -1
  89. package/dist/resources/images.d.ts +34 -0
  90. package/dist/resources/images.d.ts.map +1 -1
  91. package/dist/resources/images.js +29 -3
  92. package/dist/resources/images.js.map +1 -1
  93. package/dist/resources/leader.d.ts +10 -0
  94. package/dist/resources/leader.d.ts.map +1 -1
  95. package/dist/resources/leader.js +4 -0
  96. package/dist/resources/leader.js.map +1 -1
  97. package/dist/resources/memory.d.ts +37 -0
  98. package/dist/resources/memory.d.ts.map +1 -1
  99. package/dist/resources/memory.js +28 -0
  100. package/dist/resources/memory.js.map +1 -1
  101. package/dist/resources/models.d.ts +12 -0
  102. package/dist/resources/models.d.ts.map +1 -1
  103. package/dist/resources/models.js +4 -0
  104. package/dist/resources/models.js.map +1 -1
  105. package/dist/resources/ops.d.ts +16 -0
  106. package/dist/resources/ops.d.ts.map +1 -1
  107. package/dist/resources/ops.js +6 -0
  108. package/dist/resources/ops.js.map +1 -1
  109. package/dist/resources/policy.d.ts +8 -0
  110. package/dist/resources/policy.d.ts.map +1 -1
  111. package/dist/resources/policy.js +1 -0
  112. package/dist/resources/policy.js.map +1 -1
  113. package/dist/resources/questions.d.ts +57 -0
  114. package/dist/resources/questions.d.ts.map +1 -1
  115. package/dist/resources/questions.js +9 -0
  116. package/dist/resources/questions.js.map +1 -1
  117. package/dist/resources/runs.d.ts +143 -0
  118. package/dist/resources/runs.d.ts.map +1 -1
  119. package/dist/resources/runs.js +129 -2
  120. package/dist/resources/runs.js.map +1 -1
  121. package/dist/resources/session-sync.d.ts +61 -0
  122. package/dist/resources/session-sync.d.ts.map +1 -1
  123. package/dist/resources/session-sync.js +54 -1
  124. package/dist/resources/session-sync.js.map +1 -1
  125. package/dist/resources/sessions.d.ts +74 -0
  126. package/dist/resources/sessions.d.ts.map +1 -1
  127. package/dist/resources/sessions.js +64 -2
  128. package/dist/resources/sessions.js.map +1 -1
  129. package/dist/resources/side-query.d.ts +18 -0
  130. package/dist/resources/side-query.d.ts.map +1 -1
  131. package/dist/resources/side-query.js +1 -0
  132. package/dist/resources/side-query.js.map +1 -1
  133. package/dist/resources/tasks.d.ts +19 -0
  134. package/dist/resources/tasks.d.ts.map +1 -1
  135. package/dist/resources/tasks.js +21 -2
  136. package/dist/resources/tasks.js.map +1 -1
  137. package/dist/resources/tool-approvals.d.ts +53 -0
  138. package/dist/resources/tool-approvals.d.ts.map +1 -1
  139. package/dist/resources/tool-approvals.js +10 -0
  140. package/dist/resources/tool-approvals.js.map +1 -1
  141. package/dist/resources/trace.d.ts +23 -0
  142. package/dist/resources/trace.d.ts.map +1 -1
  143. package/dist/resources/trace.js +27 -2
  144. package/dist/resources/trace.js.map +1 -1
  145. package/dist/resources/usage.d.ts +21 -0
  146. package/dist/resources/usage.d.ts.map +1 -1
  147. package/dist/resources/usage.js +8 -0
  148. package/dist/resources/usage.js.map +1 -1
  149. package/dist/resources/workflows.d.ts +48 -0
  150. package/dist/resources/workflows.d.ts.map +1 -1
  151. package/dist/resources/workflows.js +40 -3
  152. package/dist/resources/workflows.js.map +1 -1
  153. package/dist/settings.d.ts +90 -0
  154. package/dist/settings.d.ts.map +1 -1
  155. package/dist/settings.js +24 -0
  156. package/dist/settings.js.map +1 -1
  157. package/dist/sse.d.ts +36 -0
  158. package/dist/sse.d.ts.map +1 -1
  159. package/dist/sse.js +53 -8
  160. package/dist/sse.js.map +1 -1
  161. package/dist/sync.d.ts +56 -0
  162. package/dist/sync.d.ts.map +1 -1
  163. package/dist/sync.js +48 -4
  164. package/dist/sync.js.map +1 -1
  165. package/dist/transport.d.ts +32 -0
  166. package/dist/transport.d.ts.map +1 -1
  167. package/dist/transport.js +40 -8
  168. package/dist/transport.js.map +1 -1
  169. package/dist/types.d.ts +691 -1
  170. package/dist/types.d.ts.map +1 -1
  171. package/package.json +1 -1
@@ -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":"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"}
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":"AAcA,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;IAQnC,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,eAAe,CAAC;IAgBrF,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;IAatB,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;IAmBhB,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;IAkBV,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;IAkBlB,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;IAiBlB,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
+ {"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":"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"}
1
+ {"version":3,"file":"session-sync.js","sourceRoot":"","sources":["../../src/resources/session-sync.ts"],"names":[],"mappings":"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"}