@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/sync.js
CHANGED
|
@@ -1,31 +1,54 @@
|
|
|
1
|
+
/** §7 — classify how a SOURCE log (`srcIds`, oldest-first) relates to a DESTINATION log (`dstIds`, oldest-first, or
|
|
2
|
+
* `null`/`[]` when the dst has no such session). Returns the {@link SyncRelation} discriminated union. */
|
|
1
3
|
export function classifySyncRelationshipByIds(srcIds, dstIds) {
|
|
4
|
+
// dst absent OR empty ⇒ nothing at the destination to relate to / lose → an unconditional fresh import.
|
|
2
5
|
if (dstIds === null || dstIds.length === 0)
|
|
3
6
|
return { relation: "fresh" };
|
|
4
7
|
const srcSet = new Set(srcIds);
|
|
5
8
|
const dstSet = new Set(dstIds);
|
|
9
|
+
// identical: same cardinality AND every src id is in dst (⟹ the sets are equal) → already present & equal (no-op).
|
|
6
10
|
if (srcSet.size === dstSet.size && [...srcSet].every((id) => dstSet.has(id)))
|
|
7
11
|
return { relation: "identical" };
|
|
8
|
-
const allDstInSrc = [...dstSet].every((id) => srcSet.has(id));
|
|
9
|
-
const allSrcInDst = [...srcSet].every((id) => dstSet.has(id));
|
|
12
|
+
const allDstInSrc = [...dstSet].every((id) => srcSet.has(id)); // dst ⊆ src
|
|
13
|
+
const allSrcInDst = [...srcSet].every((id) => dstSet.has(id)); // src ⊆ dst
|
|
14
|
+
// fast_forward: dst ⊊ src (src strictly ahead — a clean append) → safe to apply. newEntryIds = the src ids the dst
|
|
15
|
+
// lacks, in SRC oldest-first order (the appended tail).
|
|
10
16
|
if (allDstInSrc && !allSrcInDst) {
|
|
11
17
|
const newEntryIds = srcIds.filter((id) => !dstSet.has(id));
|
|
12
18
|
return { relation: "fast_forward", newEntryIds };
|
|
13
19
|
}
|
|
20
|
+
// stale: src ⊊ dst (src strictly behind) → applying would DROP the dst entries src never saw = data loss. dstAheadBy
|
|
21
|
+
// = the dst ids src lacks (dst order). A conflict unless the caller explicitly resolves overwrite-dst.
|
|
14
22
|
if (allSrcInDst && !allDstInSrc) {
|
|
15
23
|
const dstAheadBy = dstIds.filter((id) => !srcSet.has(id));
|
|
16
24
|
return { relation: "stale", dstAheadBy };
|
|
17
25
|
}
|
|
26
|
+
// fork: neither set contains the other ⇒ each side has ≥1 exclusive entry (true divergence). commonAncestor = the
|
|
27
|
+
// deepest shared entry = the LAST id in src oldest-first order that the dst also holds (null if no shared id).
|
|
18
28
|
const srcExclusive = srcIds.filter((id) => !dstSet.has(id));
|
|
19
29
|
const dstExclusive = dstIds.filter((id) => !srcSet.has(id));
|
|
20
30
|
let commonAncestor = null;
|
|
21
31
|
for (const id of srcIds)
|
|
22
32
|
if (dstSet.has(id))
|
|
23
|
-
commonAncestor = id;
|
|
33
|
+
commonAncestor = id; // last shared id in src oldest-first order
|
|
24
34
|
return { relation: "fork", commonAncestor, srcExclusive, dstExclusive };
|
|
25
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* PUSH one session from peer `src` into peer `dst` (same-id, cross-backend):
|
|
38
|
+
* src manifest → dst dry-run plan (§7 classify) → [conflict? return, don't write] → blobs (content-addressed
|
|
39
|
+
* PUTs) → import Phase A (small metadata + lease/active-run guards) → Phase B (pipe the src entry stream
|
|
40
|
+
* straight into the staged import — never materializes the whole log in memory beyond the NDJSON body).
|
|
41
|
+
*
|
|
42
|
+
* Conflict contract (③): a `fork`/`stale` seen at plan time is RETURNED (`{pushed:false, conflict}`) so the
|
|
43
|
+
* caller can render the divergence; a TOCTOU flip after the plan (dst advanced mid-push) THROWS the typed
|
|
44
|
+
* SyncConflictError from Phase A/B — same data-loss guard, later gate. `identical` short-circuits to a no-op.
|
|
45
|
+
* A 409 `import_in_flight`/`session_active` ConflictError from Phase A propagates as-is (retry after it settles).
|
|
46
|
+
*/
|
|
26
47
|
export async function pushSessionBundle(src, dst, sessionId, opts) {
|
|
27
48
|
const sopts = opts?.signal ? { signal: opts.signal } : {};
|
|
28
49
|
const manifest = await src.sessions.sync.manifest(sessionId, sopts);
|
|
50
|
+
// Dry-run classify BEFORE any write (and before any blob upload — don't spend bandwidth on a push the
|
|
51
|
+
// conflict gate will refuse).
|
|
29
52
|
const rel = await dst.sessions.sync.plan(sessionId, { entryIds: manifest.entryIds }, sopts);
|
|
30
53
|
if (rel.relation === "identical") {
|
|
31
54
|
return { relation: "identical", pushed: true, entryCount: 0, blobsPushed: 0, manifest, plan: rel };
|
|
@@ -41,6 +64,9 @@ export async function pushSessionBundle(src, dst, sessionId, opts) {
|
|
|
41
64
|
plan: rel,
|
|
42
65
|
};
|
|
43
66
|
}
|
|
67
|
+
// Blobs first (Phase A pre-checks presence: a referenced hash the dst lacks → 422 missing_blob). Content-
|
|
68
|
+
// addressed + idempotent — re-PUT on retry is harmless. Deduped across snapshots (a workspace file shared
|
|
69
|
+
// by N turn snapshots is one blob).
|
|
44
70
|
const seen = new Set();
|
|
45
71
|
let blobsPushed = 0;
|
|
46
72
|
for (const snap of manifest.snapshots) {
|
|
@@ -53,6 +79,8 @@ export async function pushSessionBundle(src, dst, sessionId, opts) {
|
|
|
53
79
|
blobsPushed++;
|
|
54
80
|
}
|
|
55
81
|
}
|
|
82
|
+
// Phase A — may throw the typed SyncConflictError on a TOCTOU flip (dst advanced since the plan), or the
|
|
83
|
+
// 409 lease/active-run ConflictError. Both propagate: the caller's conflict surface is the same.
|
|
56
84
|
const staged = await dst.sessions.sync.import(sessionId, {
|
|
57
85
|
entryIds: manifest.entryIds,
|
|
58
86
|
snapshots: manifest.snapshots,
|
|
@@ -61,11 +89,19 @@ export async function pushSessionBundle(src, dst, sessionId, opts) {
|
|
|
61
89
|
...(opts?.resolution ? { resolution: opts.resolution } : {}),
|
|
62
90
|
}, sopts);
|
|
63
91
|
if (!staged.stagingId) {
|
|
92
|
+
// Phase A itself classified `identical` (raced to equality) — dst already holds the log.
|
|
64
93
|
return { relation: staged.relation, pushed: true, entryCount: 0, blobsPushed, manifest, plan: rel };
|
|
65
94
|
}
|
|
95
|
+
// Phase B — pipe the src entry stream straight into the staged import (async-iterable in, NDJSON out).
|
|
66
96
|
const committed = await dst.sessions.sync.importEntries(sessionId, staged.stagingId, src.sessions.sync.entries(sessionId, undefined, sopts), sopts);
|
|
67
97
|
return { relation: committed.relation, pushed: true, entryCount: manifest.entryCount, blobsPushed, manifest, plan: rel };
|
|
68
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* PULL one session OUT of peer `src` into memory (manifest + full entry log [+ blobs]) for callers that land
|
|
101
|
+
* the state outside an engine — e.g. the sema shell converting entries into its CC-format `<id>.jsonl`.
|
|
102
|
+
* 🔴 This MATERIALIZES the whole entry log (unlike the push pipe) — the caller owns the memory trade-off.
|
|
103
|
+
* A truncated entry stream throws SyncTruncatedError (the NDJSON trailer guard) — never a silently short log.
|
|
104
|
+
*/
|
|
69
105
|
export async function pullSessionBundle(src, sessionId, opts) {
|
|
70
106
|
const sopts = opts?.signal ? { signal: opts.signal } : {};
|
|
71
107
|
const manifest = await src.sessions.sync.manifest(sessionId, sopts);
|
|
@@ -94,6 +130,14 @@ export async function pullSessionBundle(src, sessionId, opts) {
|
|
|
94
130
|
blobs,
|
|
95
131
|
};
|
|
96
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* APPLY a materialized pull into peer `dst` (the pull counterpart of `pushSessionBundle` when the caller
|
|
135
|
+
* already holds the bundle — e.g. the sema shell pulls ONCE off the cloud, lands the entries into its CC
|
|
136
|
+
* transcript AND imports the same bundle into the local engine without re-fetching). Same order + conflict
|
|
137
|
+
* contract as pushSessionBundle: dry-run plan → [conflict? return, don't write] → blob PUTs (from the pulled
|
|
138
|
+
* `blobs` map; a snapshot hash missing from the map is skipped — the dst may already hold it, and Phase A's
|
|
139
|
+
* 422 `missing_blob` stays the honest gate) → import Phase A → Phase B from the in-memory entry array.
|
|
140
|
+
*/
|
|
97
141
|
export async function importSessionBundle(dst, pulled, opts) {
|
|
98
142
|
const sopts = opts?.signal ? { signal: opts.signal } : {};
|
|
99
143
|
const { manifest, bundle, blobs } = pulled;
|
|
@@ -122,7 +166,7 @@ export async function importSessionBundle(dst, pulled, opts) {
|
|
|
122
166
|
seen.add(hash);
|
|
123
167
|
const bytes = blobs.get(hash);
|
|
124
168
|
if (!bytes)
|
|
125
|
-
continue;
|
|
169
|
+
continue; // not pulled (includeBlobs:false / partial) — Phase A 422s honestly if dst lacks it
|
|
126
170
|
await dst.sessions.sync.putBlob(sessionId, hash, bytes, sopts);
|
|
127
171
|
blobsPushed++;
|
|
128
172
|
}
|
package/dist/sync.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"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"}
|
package/dist/transport.d.ts
CHANGED
|
@@ -1,17 +1,31 @@
|
|
|
1
|
+
/** A typed-error mapper: HTTP status + parsed body (+ optional Retry-After ms) → an Error subclass. The worker
|
|
2
|
+
* plane uses toApiError (errorCode envelope); the control plane uses toControlError (registry `{error}` envelope).
|
|
3
|
+
* Injected so the SAME request/retry/timeout engine serves both without a plane-detection branch. */
|
|
1
4
|
export type ErrorMapper = (status: number, body: unknown, retryAfterMs?: number) => Error;
|
|
2
5
|
export interface TransportOptions {
|
|
3
6
|
baseUrl: string;
|
|
4
7
|
timeoutMs: number;
|
|
5
8
|
maxRetries: number;
|
|
6
9
|
fetchImpl: typeof fetch;
|
|
10
|
+
/** Per-request header assembly. The token lives ONLY inside this closure (captured at construction in
|
|
11
|
+
* client.ts / control-client.ts) — it is NEVER stored as a TransportOptions field, so a Transport instance
|
|
12
|
+
* carries no serializable secret. Default = the worker triple (Bearer authToken + x-agent-principal +
|
|
13
|
+
* content-type). ControlClient injects the registry version (Bearer registryToken + optional principal).
|
|
14
|
+
* 🔴 Two clients = two closures = two independent secrets: structurally impossible to send the worker token
|
|
15
|
+
* to the registry (or vice-versa) — there is no path-prefix token-selection branch to get wrong. */
|
|
7
16
|
buildHeaders: (idempotencyKey?: string | null) => Record<string, string>;
|
|
17
|
+
/** Status+body → typed Error. Default = the worker mapper (toApiError). ControlClient injects toControlError.
|
|
18
|
+
* The retry MATRIX is unchanged (RETRYABLE_STATUS) — only the typed surface differs, so the control plane's
|
|
19
|
+
* CAS 409 / validation 400 are surfaced (never retried), identical to how the worker treats its 409. */
|
|
8
20
|
mapError?: ErrorMapper;
|
|
9
21
|
}
|
|
22
|
+
/** Statuses the SDK retries (with backoff). 409 is NOT here — it's a semantic conflict, surfaced typed. */
|
|
10
23
|
export declare const RETRYABLE_STATUS: Set<number>;
|
|
11
24
|
export interface RequestOptions {
|
|
12
25
|
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
13
26
|
path: string;
|
|
14
27
|
body?: unknown;
|
|
28
|
+
/** submit-class (POST tasks/runs) → governs the idempotency/retry red line. */
|
|
15
29
|
submit?: boolean;
|
|
16
30
|
idempotencyKey?: string | null | undefined;
|
|
17
31
|
signal?: AbortSignal | undefined;
|
|
@@ -20,20 +34,38 @@ export declare class Transport {
|
|
|
20
34
|
private readonly o;
|
|
21
35
|
constructor(o: TransportOptions);
|
|
22
36
|
headers(idempotencyKey?: string | null): Record<string, string>;
|
|
37
|
+
/** JSON request with timeout + retry matrix + typed errors. */
|
|
23
38
|
request<T>(opts: RequestOptions): Promise<T>;
|
|
39
|
+
/** Raw streaming fetch (returns the Response for sse.ts to parse). NO per-attempt timeout (a stream lives
|
|
40
|
+
* long); heartbeat watchdog lives in sse.ts. Resume/retry policy is the caller's (parseSse loop).
|
|
41
|
+
* `headers` = generic caller extras (e.g. a shell's `x-detach-on-disconnect` — the SDK carries NO detach
|
|
42
|
+
* semantics; the caller assembles them). 🔴 Merge order: caller extras first, BUILT-INS ALWAYS WIN —
|
|
43
|
+
* authorization / x-agent-principal / idempotency-key / content-type / accept / last-event-id can never be
|
|
44
|
+
* shadowed by a caller header (keys are lowercased before the merge so a mixed-case alias can't sneak past,
|
|
45
|
+
* and RESERVED keys are dropped outright — even one an explicit `idempotencyKey: null` left unset). */
|
|
24
46
|
openStream(opts: RequestOptions & {
|
|
25
47
|
lastEventId?: string;
|
|
26
48
|
headers?: Record<string, string>;
|
|
27
49
|
}): Promise<Response>;
|
|
50
|
+
/** Raw fetch (NO body re-serialization, NO timeout) for the 2c session-sync content-addressed blob + NDJSON
|
|
51
|
+
* surfaces, which the JSON `request<T>` engine cannot serve: a blob PUT carries RAW bytes (not JSON.stringify),
|
|
52
|
+
* a blob GET returns octet-stream, and the entry stream is a long-lived NDJSON body (not a single JSON parse).
|
|
53
|
+
* Returns the Response untouched so the caller drives the body (arrayBuffer / NDJSON line reader) and the
|
|
54
|
+
* status handling. `accept`/`content-type` come from `opts` (default = the buildHeaders content-type). NO retry
|
|
55
|
+
* (a stream lives long; a blob PUT is content-addressed-idempotent but unbounded → the caller decides). */
|
|
28
56
|
openRaw(opts: {
|
|
29
57
|
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
30
58
|
path: string;
|
|
59
|
+
/** RAW request body (bytes for a blob PUT, an NDJSON string for a Phase-B stream). NOT JSON-serialized. */
|
|
31
60
|
rawBody?: Uint8Array | string;
|
|
32
61
|
accept?: string;
|
|
33
62
|
contentType?: string;
|
|
63
|
+
/** Generic caller extras — SAME reserved-guard + merge order as openStream (built-ins always win;
|
|
64
|
+
* reserved keys dropped outright). E.g. the bake-runner `x-bake-ingest-secret`. */
|
|
34
65
|
headers?: Record<string, string>;
|
|
35
66
|
signal?: AbortSignal | undefined;
|
|
36
67
|
}): Promise<Response>;
|
|
68
|
+
/** Per-attempt signal = a fresh request timeout, combined with the caller's signal if any. */
|
|
37
69
|
private attemptSignal;
|
|
38
70
|
}
|
|
39
71
|
//# sourceMappingURL=transport.d.ts.map
|
package/dist/transport.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAcA;;sGAEsG;AACtG,MAAM,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,KAAK,CAAC;AAE1F,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,KAAK,CAAC;IACxB;;;;;4GAKwG;IACxG,YAAY,EAAE,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzE;;6GAEyG;IACzG,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB;AAED,2GAA2G;AAC3G,eAAO,MAAM,gBAAgB,aAA0C,CAAC;AAUxE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,+EAA+E;IAC/E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3C,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAClC;AAED,qBAAa,SAAS;IACR,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAD,CAAC,EAAE,gBAAgB;IAEhD,OAAO,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAI/D,+DAA+D;IACzD,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;IA4ClD;;;;;;4GAMwG;IAClG,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,CAAC;IAetH;;;;;gHAK4G;IACtG,OAAO,CAAC,IAAI,EAAE;QAClB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;QACpD,IAAI,EAAE,MAAM,CAAC;QACb,2GAA2G;QAC3G,OAAO,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;QAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB;4FACoF;QACpF,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;KAClC,GAAG,OAAO,CAAC,QAAQ,CAAC;IAmBrB,8FAA8F;IAC9F,OAAO,CAAC,aAAa;CAatB"}
|
package/dist/transport.js
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fetch wrapper: timeout (AbortSignal), retry policy (connect-err/408/429/5xx, exp backoff + jitter, honor
|
|
3
|
+
* Retry-After; default 2), Idempotency-Key, error mapping. principal + authToken injected per request.
|
|
4
|
+
*
|
|
5
|
+
* 🔴 retry red line (idempotency.ts): a submit (POST tasks/runs) retries ONLY with an idempotency key.
|
|
6
|
+
* A non-submit POST (e.g. approvals.decide) is NOT retried (could double-act). GETs always retry.
|
|
7
|
+
* 🔴 streaming retry is "establish connection" only; an established stream that drops resumes via Last-Event-ID
|
|
8
|
+
* (sse.ts) and does NOT consume a retry count.
|
|
9
|
+
*
|
|
10
|
+
* STATUS: M1 — request() implemented + consumer contract tests. openStream() is TODO(M2).
|
|
11
|
+
*/
|
|
1
12
|
import { toApiError } from "./errors.js";
|
|
2
13
|
import { resolveIdempotencyKey } from "./idempotency.js";
|
|
14
|
+
/** Statuses the SDK retries (with backoff). 409 is NOT here — it's a semantic conflict, surfaced typed. */
|
|
3
15
|
export const RETRYABLE_STATUS = new Set([408, 429, 500, 502, 503, 504]);
|
|
16
|
+
/** Header keys a caller-supplied `headers` extra may NEVER set (openStream merge): auth + idempotency +
|
|
17
|
+
* protocol headers are the transport's alone. Lowercase (extras are lowercased before the check). */
|
|
4
18
|
const RESERVED_HEADERS = new Set(["authorization", "x-agent-principal", "content-type", "idempotency-key", "accept", "last-event-id"]);
|
|
5
19
|
const BACKOFF_BASE_MS = 250;
|
|
6
20
|
const BACKOFF_CAP_MS = 10_000;
|
|
@@ -13,7 +27,9 @@ export class Transport {
|
|
|
13
27
|
headers(idempotencyKey) {
|
|
14
28
|
return this.o.buildHeaders(idempotencyKey);
|
|
15
29
|
}
|
|
30
|
+
/** JSON request with timeout + retry matrix + typed errors. */
|
|
16
31
|
async request(opts) {
|
|
32
|
+
// Submit-class gets an idempotency key (auto unless explicitly null). The key gates submit retry.
|
|
17
33
|
const key = opts.submit ? resolveIdempotencyKey(opts.idempotencyKey) : null;
|
|
18
34
|
const canRetry = opts.method === "GET" || (opts.submit === true && key !== null);
|
|
19
35
|
const maxAttempts = canRetry ? this.o.maxRetries + 1 : 1;
|
|
@@ -34,8 +50,8 @@ export class Transport {
|
|
|
34
50
|
}
|
|
35
51
|
catch (e) {
|
|
36
52
|
if (opts.signal?.aborted)
|
|
37
|
-
throw e;
|
|
38
|
-
lastErr = e;
|
|
53
|
+
throw e; // caller cancelled → never retry
|
|
54
|
+
lastErr = e; // request timeout or connect/network error → retryable (if allowed)
|
|
39
55
|
if (attempt < maxAttempts - 1) {
|
|
40
56
|
await sleep(backoff(attempt));
|
|
41
57
|
continue;
|
|
@@ -49,13 +65,20 @@ export class Transport {
|
|
|
49
65
|
const err = mapError(res.status, await safeJson(res), retryAfterMs);
|
|
50
66
|
if (RETRYABLE_STATUS.has(res.status) && attempt < maxAttempts - 1) {
|
|
51
67
|
lastErr = err;
|
|
52
|
-
await sleep(Math.min(retryAfterMs ?? backoff(attempt), RETRY_AFTER_CAP_MS));
|
|
68
|
+
await sleep(Math.min(retryAfterMs ?? backoff(attempt), RETRY_AFTER_CAP_MS)); // cap: never park a caller for minutes
|
|
53
69
|
continue;
|
|
54
70
|
}
|
|
55
|
-
throw err;
|
|
71
|
+
throw err; // 409 conflict (typed, with activeTaskId) lands here — surfaced, NOT auto-resolved (pinned wire contract)
|
|
56
72
|
}
|
|
57
|
-
throw lastErr;
|
|
73
|
+
throw lastErr; // exhausted retries
|
|
58
74
|
}
|
|
75
|
+
/** Raw streaming fetch (returns the Response for sse.ts to parse). NO per-attempt timeout (a stream lives
|
|
76
|
+
* long); heartbeat watchdog lives in sse.ts. Resume/retry policy is the caller's (parseSse loop).
|
|
77
|
+
* `headers` = generic caller extras (e.g. a shell's `x-detach-on-disconnect` — the SDK carries NO detach
|
|
78
|
+
* semantics; the caller assembles them). 🔴 Merge order: caller extras first, BUILT-INS ALWAYS WIN —
|
|
79
|
+
* authorization / x-agent-principal / idempotency-key / content-type / accept / last-event-id can never be
|
|
80
|
+
* shadowed by a caller header (keys are lowercased before the merge so a mixed-case alias can't sneak past,
|
|
81
|
+
* and RESERVED keys are dropped outright — even one an explicit `idempotencyKey: null` left unset). */
|
|
59
82
|
async openStream(opts) {
|
|
60
83
|
const extras = {};
|
|
61
84
|
for (const [k, v] of Object.entries(opts.headers ?? {})) {
|
|
@@ -74,6 +97,12 @@ export class Transport {
|
|
|
74
97
|
init.signal = opts.signal;
|
|
75
98
|
return this.o.fetchImpl(this.o.baseUrl.replace(/\/+$/, "") + opts.path, init);
|
|
76
99
|
}
|
|
100
|
+
/** Raw fetch (NO body re-serialization, NO timeout) for the 2c session-sync content-addressed blob + NDJSON
|
|
101
|
+
* surfaces, which the JSON `request<T>` engine cannot serve: a blob PUT carries RAW bytes (not JSON.stringify),
|
|
102
|
+
* a blob GET returns octet-stream, and the entry stream is a long-lived NDJSON body (not a single JSON parse).
|
|
103
|
+
* Returns the Response untouched so the caller drives the body (arrayBuffer / NDJSON line reader) and the
|
|
104
|
+
* status handling. `accept`/`content-type` come from `opts` (default = the buildHeaders content-type). NO retry
|
|
105
|
+
* (a stream lives long; a blob PUT is content-addressed-idempotent but unbounded → the caller decides). */
|
|
77
106
|
async openRaw(opts) {
|
|
78
107
|
const extras = {};
|
|
79
108
|
for (const [k, v] of Object.entries(opts.headers ?? {})) {
|
|
@@ -87,10 +116,10 @@ export class Transport {
|
|
|
87
116
|
if (opts.contentType)
|
|
88
117
|
h["content-type"] = opts.contentType;
|
|
89
118
|
else
|
|
90
|
-
delete h["content-type"];
|
|
119
|
+
delete h["content-type"]; // a GET / a no-body request should not assert a JSON content-type
|
|
91
120
|
const init = { method: opts.method, headers: h };
|
|
92
121
|
if (opts.rawBody !== undefined) {
|
|
93
|
-
init.body = opts.rawBody;
|
|
122
|
+
init.body = opts.rawBody; // Uint8Array is a valid fetch body at runtime (the DOM BodyInit lib type omits it)
|
|
94
123
|
if (!opts.contentType)
|
|
95
124
|
h["content-type"] = "application/octet-stream";
|
|
96
125
|
}
|
|
@@ -98,6 +127,7 @@ export class Transport {
|
|
|
98
127
|
init.signal = opts.signal;
|
|
99
128
|
return this.o.fetchImpl(this.o.baseUrl.replace(/\/+$/, "") + opts.path, init);
|
|
100
129
|
}
|
|
130
|
+
/** Per-attempt signal = a fresh request timeout, combined with the caller's signal if any. */
|
|
101
131
|
attemptSignal(caller) {
|
|
102
132
|
const timeout = AbortSignal.timeout(this.o.timeoutMs);
|
|
103
133
|
if (!caller)
|
|
@@ -105,6 +135,7 @@ export class Transport {
|
|
|
105
135
|
const anyOf = AbortSignal.any;
|
|
106
136
|
if (typeof anyOf === "function")
|
|
107
137
|
return anyOf([caller, timeout]);
|
|
138
|
+
// Fallback for runtimes without AbortSignal.any: manual combine.
|
|
108
139
|
const ac = new AbortController();
|
|
109
140
|
const abort = (s) => ac.abort(s.reason);
|
|
110
141
|
if (caller.aborted)
|
|
@@ -117,11 +148,12 @@ export class Transport {
|
|
|
117
148
|
}
|
|
118
149
|
function backoff(attempt) {
|
|
119
150
|
const exp = Math.min(BACKOFF_BASE_MS * 2 ** attempt, BACKOFF_CAP_MS);
|
|
120
|
-
return exp + Math.random() * BACKOFF_BASE_MS;
|
|
151
|
+
return exp + Math.random() * BACKOFF_BASE_MS; // jitter
|
|
121
152
|
}
|
|
122
153
|
function sleep(ms) {
|
|
123
154
|
return new Promise((r) => setTimeout(r, ms));
|
|
124
155
|
}
|
|
156
|
+
/** `Retry-After` is delta-seconds or an HTTP-date. Returns ms, or undefined if absent/unparseable. */
|
|
125
157
|
function parseRetryAfter(h) {
|
|
126
158
|
if (!h)
|
|
127
159
|
return undefined;
|
package/dist/transport.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"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"}
|