@shardlink/agent-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +129 -0
  3. package/dist/client-quick-join.d.ts +38 -0
  4. package/dist/client-quick-join.d.ts.map +1 -0
  5. package/dist/client-quick-join.js +141 -0
  6. package/dist/client-quick-join.js.map +1 -0
  7. package/dist/client.d.ts +134 -0
  8. package/dist/client.d.ts.map +1 -0
  9. package/dist/client.js +190 -0
  10. package/dist/client.js.map +1 -0
  11. package/dist/errors.d.ts +126 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/errors.js +330 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/index.d.ts +47 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +47 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/modules/a2a.d.ts +42 -0
  20. package/dist/modules/a2a.d.ts.map +1 -0
  21. package/dist/modules/a2a.js +47 -0
  22. package/dist/modules/a2a.js.map +1 -0
  23. package/dist/modules/agents.d.ts +100 -0
  24. package/dist/modules/agents.d.ts.map +1 -0
  25. package/dist/modules/agents.js +85 -0
  26. package/dist/modules/agents.js.map +1 -0
  27. package/dist/modules/auth.d.ts +49 -0
  28. package/dist/modules/auth.d.ts.map +1 -0
  29. package/dist/modules/auth.js +69 -0
  30. package/dist/modules/auth.js.map +1 -0
  31. package/dist/modules/billing.d.ts +254 -0
  32. package/dist/modules/billing.d.ts.map +1 -0
  33. package/dist/modules/billing.js +203 -0
  34. package/dist/modules/billing.js.map +1 -0
  35. package/dist/modules/clans.d.ts +73 -0
  36. package/dist/modules/clans.d.ts.map +1 -0
  37. package/dist/modules/clans.js +94 -0
  38. package/dist/modules/clans.js.map +1 -0
  39. package/dist/modules/compliance.d.ts +97 -0
  40. package/dist/modules/compliance.d.ts.map +1 -0
  41. package/dist/modules/compliance.js +227 -0
  42. package/dist/modules/compliance.js.map +1 -0
  43. package/dist/modules/cross-plane.d.ts +164 -0
  44. package/dist/modules/cross-plane.d.ts.map +1 -0
  45. package/dist/modules/cross-plane.js +195 -0
  46. package/dist/modules/cross-plane.js.map +1 -0
  47. package/dist/modules/dashboard.d.ts +130 -0
  48. package/dist/modules/dashboard.d.ts.map +1 -0
  49. package/dist/modules/dashboard.js +120 -0
  50. package/dist/modules/dashboard.js.map +1 -0
  51. package/dist/modules/degradation.d.ts +120 -0
  52. package/dist/modules/degradation.d.ts.map +1 -0
  53. package/dist/modules/degradation.js +205 -0
  54. package/dist/modules/degradation.js.map +1 -0
  55. package/dist/modules/diagnostics-checks.d.ts +32 -0
  56. package/dist/modules/diagnostics-checks.d.ts.map +1 -0
  57. package/dist/modules/diagnostics-checks.js +231 -0
  58. package/dist/modules/diagnostics-checks.js.map +1 -0
  59. package/dist/modules/diagnostics-types.d.ts +118 -0
  60. package/dist/modules/diagnostics-types.d.ts.map +1 -0
  61. package/dist/modules/diagnostics-types.js +16 -0
  62. package/dist/modules/diagnostics-types.js.map +1 -0
  63. package/dist/modules/diagnostics.d.ts +64 -0
  64. package/dist/modules/diagnostics.d.ts.map +1 -0
  65. package/dist/modules/diagnostics.js +206 -0
  66. package/dist/modules/diagnostics.js.map +1 -0
  67. package/dist/modules/discovery.d.ts +152 -0
  68. package/dist/modules/discovery.d.ts.map +1 -0
  69. package/dist/modules/discovery.js +100 -0
  70. package/dist/modules/discovery.js.map +1 -0
  71. package/dist/modules/fleets.d.ts +82 -0
  72. package/dist/modules/fleets.d.ts.map +1 -0
  73. package/dist/modules/fleets.js +33 -0
  74. package/dist/modules/fleets.js.map +1 -0
  75. package/dist/modules/lease-manager.d.ts +119 -0
  76. package/dist/modules/lease-manager.d.ts.map +1 -0
  77. package/dist/modules/lease-manager.js +242 -0
  78. package/dist/modules/lease-manager.js.map +1 -0
  79. package/dist/modules/leases.d.ts +70 -0
  80. package/dist/modules/leases.d.ts.map +1 -0
  81. package/dist/modules/leases.js +51 -0
  82. package/dist/modules/leases.js.map +1 -0
  83. package/dist/modules/operators.d.ts +176 -0
  84. package/dist/modules/operators.d.ts.map +1 -0
  85. package/dist/modules/operators.js +133 -0
  86. package/dist/modules/operators.js.map +1 -0
  87. package/dist/modules/providers.d.ts +141 -0
  88. package/dist/modules/providers.d.ts.map +1 -0
  89. package/dist/modules/providers.js +118 -0
  90. package/dist/modules/providers.js.map +1 -0
  91. package/dist/modules/quota.d.ts +102 -0
  92. package/dist/modules/quota.d.ts.map +1 -0
  93. package/dist/modules/quota.js +135 -0
  94. package/dist/modules/quota.js.map +1 -0
  95. package/dist/modules/reactions.d.ts +141 -0
  96. package/dist/modules/reactions.d.ts.map +1 -0
  97. package/dist/modules/reactions.js +122 -0
  98. package/dist/modules/reactions.js.map +1 -0
  99. package/dist/modules/register.d.ts +159 -0
  100. package/dist/modules/register.d.ts.map +1 -0
  101. package/dist/modules/register.js +239 -0
  102. package/dist/modules/register.js.map +1 -0
  103. package/dist/modules/sandbox.d.ts +106 -0
  104. package/dist/modules/sandbox.d.ts.map +1 -0
  105. package/dist/modules/sandbox.js +224 -0
  106. package/dist/modules/sandbox.js.map +1 -0
  107. package/dist/modules/streams.d.ts +81 -0
  108. package/dist/modules/streams.d.ts.map +1 -0
  109. package/dist/modules/streams.js +292 -0
  110. package/dist/modules/streams.js.map +1 -0
  111. package/dist/modules/tasks.d.ts +145 -0
  112. package/dist/modules/tasks.d.ts.map +1 -0
  113. package/dist/modules/tasks.js +165 -0
  114. package/dist/modules/tasks.js.map +1 -0
  115. package/dist/modules/telemetry.d.ts +137 -0
  116. package/dist/modules/telemetry.d.ts.map +1 -0
  117. package/dist/modules/telemetry.js +203 -0
  118. package/dist/modules/telemetry.js.map +1 -0
  119. package/dist/modules/workspace.d.ts +180 -0
  120. package/dist/modules/workspace.d.ts.map +1 -0
  121. package/dist/modules/workspace.js +157 -0
  122. package/dist/modules/workspace.js.map +1 -0
  123. package/dist/quickstart-join.d.ts +56 -0
  124. package/dist/quickstart-join.d.ts.map +1 -0
  125. package/dist/quickstart-join.js +116 -0
  126. package/dist/quickstart-join.js.map +1 -0
  127. package/dist/quickstart.d.ts +137 -0
  128. package/dist/quickstart.d.ts.map +1 -0
  129. package/dist/quickstart.js +292 -0
  130. package/dist/quickstart.js.map +1 -0
  131. package/dist/retry.d.ts +88 -0
  132. package/dist/retry.d.ts.map +1 -0
  133. package/dist/retry.js +152 -0
  134. package/dist/retry.js.map +1 -0
  135. package/dist/types.d.ts +447 -0
  136. package/dist/types.d.ts.map +1 -0
  137. package/dist/types.js +10 -0
  138. package/dist/types.js.map +1 -0
  139. package/dist/utils.d.ts +88 -0
  140. package/dist/utils.d.ts.map +1 -0
  141. package/dist/utils.js +199 -0
  142. package/dist/utils.js.map +1 -0
  143. package/package.json +215 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quickstart.d.ts","sourceRoot":"","sources":["../src/quickstart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,cAAc,EAA8B,MAAM,aAAa,CAAC;AACzE,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAErE,OAAO,KAAK,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACzF,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACnG,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEpE,6CAA6C;AAC7C,MAAM,WAAW,gBAAgB;IAC/B,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAC1C;;;OAGG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC,GAAG;QAAE,OAAO,CAAC,EAAE,iBAAiB,CAAC,SAAS,CAAC,CAAA;KAAE,CAAC;IACzF,8CAA8C;IAC9C,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,mFAAmF;IACnF,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,wBAAwB,CAAC;IACpC;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,2DAA2D;IAC3D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C;;;;;;;;;;;;;;;;OAgBG;IACH,WAAW,CAAC,EAAE;QACZ,UAAU,EAAE,MAAM,CAAC;QACnB,mFAAmF;QACnF,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE;YACb,MAAM,EAAE,cAAc,CAAC;YACvB,aAAa,EAAE,MAAM,CAAC;YACtB,iBAAiB,EAAE,MAAM,CAAC;SAC3B,KAAK,OAAO,CAAC,KAAK,CAAC;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;SAAE,CAAC,CAAC,CAAC;KAC5D,CAAC;CACH;AAED,2DAA2D;AAC3D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,0EAA0E;IAC1E,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IACpC,oEAAoE;IACpE,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC5C,+BAA+B;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC9E,gDAAgD;IAChD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,wDAAwD;AACxD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,8DAA8D;IAC9D,KAAK,EAAE,WAAW,CAAC;CACpB;AAaD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAkOhF"}
@@ -0,0 +1,292 @@
1
+ /**
2
+ * `quickStart` — the zero-to-earning composer.
3
+ *
4
+ * Goal: if an agent meets the basic requirements (wallet OR service token,
5
+ * supported adapter), one call here should take it from "nothing" to
6
+ * "listening for claimable tasks" in under 60 seconds.
7
+ *
8
+ * Composition:
9
+ * 1. Ensure a session (reuse wallet or service token)
10
+ * 2. Quick-join a workspace (register runtime, bootstrap, fund, lease)
11
+ * 3. Open the workspace event stream
12
+ * 4. Return a {@link RunningAgent} handle that exposes the task stream and
13
+ * lifecycle helpers
14
+ *
15
+ * @packageDocumentation
16
+ */
17
+ import { AgentSdkClient } from "./client.js";
18
+ import { openStream } from "./modules/streams.js";
19
+ import { resolveJoinInput, runQuickJoin } from "./quickstart-join.js";
20
+ function toClientOptions(config, tokenProvider) {
21
+ return {
22
+ baseUrl: config.baseUrl,
23
+ getToken: tokenProvider,
24
+ ...(config.fetchImpl ? { fetchImpl: config.fetchImpl } : {})
25
+ };
26
+ }
27
+ /**
28
+ * Take an agent from zero to listening for work.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * const agent = await quickStart({
33
+ * baseUrl: process.env.SHARDLINK_BASE_URL!,
34
+ * getToken: () => process.env.SHARDLINK_SERVICE_TOKEN!,
35
+ * join: {
36
+ * identity: "agent_1",
37
+ * runtime: { runtimeKey: "openclaw", runtimeVersion: "1.0.0",
38
+ * adapterKind: "openclaw",
39
+ * supportedActions: ["claim_task", "complete_task"] }
40
+ * }
41
+ * });
42
+ *
43
+ * for await (const task of agent.tasks) {
44
+ * const claimed = await agent.claim(task.id);
45
+ * if (claimed.winner) {
46
+ * await agent.complete(task.id, { kind: "text", content: "done" });
47
+ * }
48
+ * }
49
+ * ```
50
+ */
51
+ export async function quickStart(config) {
52
+ if (!config.getToken && !config.wallet) {
53
+ throw new Error("[quickStart] must provide either `getToken` or `wallet` config to mint a session.");
54
+ }
55
+ // Resolve a session: either use the caller's token, or self-register with a wallet.
56
+ let tokenProvider;
57
+ let selfRegisterResult = null;
58
+ if (config.getToken) {
59
+ tokenProvider = config.getToken;
60
+ }
61
+ else {
62
+ const bootstrapClient = new AgentSdkClient({
63
+ baseUrl: config.baseUrl,
64
+ ...(config.fetchImpl ? { fetchImpl: config.fetchImpl } : {})
65
+ });
66
+ const runtime = config.wallet?.runtime ??
67
+ config.join?.runtime ??
68
+ undefined;
69
+ if (!runtime) {
70
+ throw new Error("[quickStart] must provide `wallet.runtime` or `join.runtime` when self-registering.");
71
+ }
72
+ selfRegisterResult = await bootstrapClient.register.selfRegister({
73
+ ...config.wallet,
74
+ runtime
75
+ });
76
+ const sessionToken = selfRegisterResult.session.token;
77
+ tokenProvider = () => sessionToken;
78
+ }
79
+ const client = new AgentSdkClient(toClientOptions(config, tokenProvider));
80
+ // Build the quickJoin input — filling in defaults from self-register + discover when needed.
81
+ const joinInput = await resolveJoinInput(client, config, selfRegisterResult);
82
+ const join = await runQuickJoin(client, joinInput);
83
+ const actorSessionToken = join.actorSessionToken;
84
+ const stream = openStream({
85
+ baseUrl: client.baseUrl,
86
+ workspace: join.workspace.slug,
87
+ role: "agent",
88
+ getToken: () => actorSessionToken,
89
+ ...(config.onStreamStateChange ? { onStateChange: (s) => config.onStreamStateChange?.(s) } : {})
90
+ });
91
+ const identity = joinInput.identity ??
92
+ joinInput.runtime.identity ??
93
+ selfRegisterResult?.identity ??
94
+ extractIdentity(join.bootstrap) ??
95
+ "self";
96
+ const taskQueue = [];
97
+ const waiters = [];
98
+ const seenTaskIds = new Set();
99
+ let closed = false;
100
+ const offer = (id, event) => {
101
+ if (seenTaskIds.has(id) || closed)
102
+ return;
103
+ seenTaskIds.add(id);
104
+ const task = { id, event };
105
+ if (waiters.length > 0) {
106
+ const resolve = waiters.shift();
107
+ resolve?.({ value: task, done: false });
108
+ }
109
+ else {
110
+ taskQueue.push(task);
111
+ }
112
+ };
113
+ // Stream-driven task discovery. The control-plane SSE stream emits native
114
+ // task-lifecycle events — `task_ready_for_claim` (a task is open for
115
+ // claiming), `task_claimed`, and `task_completed` — alongside the reactions
116
+ // snapshot + `reaction_event` feed. `task_created` is also handled
117
+ // defensively: it is not currently emitted by the control plane, but the
118
+ // synthetic poll-fallback event below carries that type, and accepting it
119
+ // costs nothing if a future server revision starts emitting it.
120
+ const unsubStream = stream.onAny((event) => {
121
+ const payload = event.payload;
122
+ if (event.type === "task_created" ||
123
+ event.type === "task_ready_for_claim" ||
124
+ event.type === "task_claimed" ||
125
+ event.type === "task_completed") {
126
+ const id = extractId(payload);
127
+ if (id)
128
+ offer(id, event);
129
+ return;
130
+ }
131
+ if (event.type === "snapshot" && isRecord(payload) && Array.isArray(payload.items)) {
132
+ for (const item of payload.items) {
133
+ const id = extractId(item);
134
+ if (id)
135
+ offer(id, event);
136
+ }
137
+ return;
138
+ }
139
+ if (event.type === "reaction_event" && isRecord(payload)) {
140
+ // Reactions can target tasks — when they do, surface the task for eligible agents.
141
+ if (payload.targetType === "task") {
142
+ const id = typeof payload.targetId === "string" ? payload.targetId : undefined;
143
+ if (id)
144
+ offer(id, event);
145
+ }
146
+ }
147
+ });
148
+ // Polling fallback — ON by default as defense-in-depth. The stream above
149
+ // surfaces task-lifecycle events natively, but an SSE connection can drop
150
+ // and miss events while reconnecting; the 5s poll covers that gap.
151
+ const pollConfig = config.taskPolling ?? { intervalMs: 5_000 };
152
+ let pollTimer = null;
153
+ if (pollConfig.intervalMs > 0) {
154
+ const lister = pollConfig.list ??
155
+ (async ({ client: c, workspaceSlug, actorSessionToken: tok }) => {
156
+ const params = new URLSearchParams({ status: "pending" });
157
+ try {
158
+ const res = await c.http.rawRequest({
159
+ path: `/v1/workspaces/${encodeURIComponent(workspaceSlug)}/tasks`,
160
+ method: "GET",
161
+ operation: "task-list-poll",
162
+ headers: c.http.bearerHeaders(tok),
163
+ params
164
+ });
165
+ if (!res.ok)
166
+ return [];
167
+ const json = (await res.json());
168
+ return Array.isArray(json.tasks) ? json.tasks : [];
169
+ }
170
+ catch {
171
+ return [];
172
+ }
173
+ });
174
+ pollTimer = setInterval(() => {
175
+ if (closed)
176
+ return;
177
+ void lister({
178
+ client,
179
+ workspaceSlug: join.workspace.slug,
180
+ actorSessionToken
181
+ }).then((tasks) => {
182
+ // Synthetic envelope tagging polled tasks — distinguishes a
183
+ // poll-discovered task from a stream-discovered one on the
184
+ // `ClaimableTask.event` field surfaced to callers.
185
+ const syntheticEvent = { type: "task_created", payload: null };
186
+ for (const task of tasks) {
187
+ if (typeof task.id === "string")
188
+ offer(task.id, syntheticEvent);
189
+ }
190
+ });
191
+ }, pollConfig.intervalMs);
192
+ }
193
+ const tasks = {
194
+ [Symbol.asyncIterator]() {
195
+ return {
196
+ next() {
197
+ if (taskQueue.length > 0) {
198
+ const task = taskQueue.shift();
199
+ return Promise.resolve({ value: task, done: false });
200
+ }
201
+ if (closed) {
202
+ return Promise.resolve({ value: undefined, done: true });
203
+ }
204
+ return new Promise((resolve) => waiters.push(resolve));
205
+ },
206
+ return() {
207
+ closed = true;
208
+ if (pollTimer) {
209
+ clearInterval(pollTimer);
210
+ pollTimer = null;
211
+ }
212
+ try {
213
+ unsubStream();
214
+ }
215
+ catch {
216
+ // ignore
217
+ }
218
+ waiters.forEach((resolve) => resolve({ value: undefined, done: true }));
219
+ waiters.length = 0;
220
+ return Promise.resolve({ value: undefined, done: true });
221
+ }
222
+ };
223
+ }
224
+ };
225
+ return {
226
+ identity,
227
+ workspace: join.workspace.slug,
228
+ actorSessionToken,
229
+ join,
230
+ client,
231
+ stream,
232
+ tasks,
233
+ async claim(taskId) {
234
+ return client.tasks.claim({
235
+ workspaceSlug: join.workspace.slug,
236
+ actorSessionToken,
237
+ taskId
238
+ });
239
+ },
240
+ async complete(taskId, artifact) {
241
+ return client.tasks.complete({
242
+ workspaceSlug: join.workspace.slug,
243
+ actorSessionToken,
244
+ taskId,
245
+ artifact
246
+ });
247
+ },
248
+ async shutdown() {
249
+ closed = true;
250
+ if (pollTimer) {
251
+ clearInterval(pollTimer);
252
+ pollTimer = null;
253
+ }
254
+ try {
255
+ unsubStream();
256
+ }
257
+ catch {
258
+ // ignore
259
+ }
260
+ waiters.forEach((resolve) => resolve({ value: undefined, done: true }));
261
+ waiters.length = 0;
262
+ stream.disconnect();
263
+ }
264
+ };
265
+ }
266
+ function isRecord(value) {
267
+ return typeof value === "object" && value !== null;
268
+ }
269
+ function extractId(payload) {
270
+ if (!isRecord(payload))
271
+ return undefined;
272
+ if (typeof payload.taskId === "string")
273
+ return payload.taskId;
274
+ if (typeof payload.id === "string")
275
+ return payload.id;
276
+ if (isRecord(payload.task) && typeof payload.task.id === "string")
277
+ return payload.task.id;
278
+ return undefined;
279
+ }
280
+ function extractIdentity(payload) {
281
+ if (!isRecord(payload))
282
+ return undefined;
283
+ const envelope = isRecord(payload.envelope) ? payload.envelope : undefined;
284
+ if (envelope && typeof envelope.identity === "string") {
285
+ return envelope.identity;
286
+ }
287
+ if (typeof payload.identity === "string") {
288
+ return payload.identity;
289
+ }
290
+ return undefined;
291
+ }
292
+ //# sourceMappingURL=quickstart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quickstart.js","sourceRoot":"","sources":["../src/quickstart.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Smart retry policies and idempotency-key helpers.
3
+ *
4
+ * The default policy only retries errors the control-plane marked as
5
+ * retryable, respects server-supplied `Retry-After`, and adds jitter so
6
+ * independent clients don't synchronise on a thundering herd.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ /** Callback invoked before every retry sleep. */
11
+ export type RetryAttemptHook = (info: {
12
+ /** 1-indexed attempt number that just failed. */
13
+ attempt: number;
14
+ /** The error that caused the retry. */
15
+ error: unknown;
16
+ /** Milliseconds the retry loop will sleep before the next attempt. */
17
+ delayMs: number;
18
+ /** Total attempts allowed by the policy (including the first). */
19
+ maxAttempts: number;
20
+ }) => void;
21
+ /** Configuration for {@link withRetry}. */
22
+ export interface RetryPolicy {
23
+ /** Max attempts including the first (so `3` = one try + two retries). */
24
+ maxAttempts: number;
25
+ /** Base delay in milliseconds before doubling. */
26
+ baseDelay: number;
27
+ /** Cap for the exponential backoff. */
28
+ maxDelay: number;
29
+ /** 0..1 jitter factor applied to each delay. */
30
+ jitter: number;
31
+ /** If present, only retry when `error.code` is in this list. */
32
+ retryOn?: string[];
33
+ /** Abort retrying early (e.g. on shutdown). */
34
+ signal?: AbortSignal;
35
+ /**
36
+ * Observability hook — fires once per retry *before* the backoff sleep.
37
+ * Useful for structured logging and TelemetryClient spans. Sink failures
38
+ * never propagate; a thrown hook is swallowed.
39
+ */
40
+ onAttempt?: RetryAttemptHook;
41
+ }
42
+ /** Reasonable defaults — safe for any idempotent mutation. */
43
+ export declare const DEFAULT_RETRY: RetryPolicy;
44
+ /**
45
+ * Generate an idempotency key suitable for HTTP `Idempotency-Key` headers.
46
+ *
47
+ * @param prefix - A stable prefix identifying the logical operation.
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * const key = idempotencyKey("task-claim:task_123");
52
+ * // → "task-claim:task_123:01J...Z"
53
+ * ```
54
+ */
55
+ export declare function idempotencyKey(prefix: string): string;
56
+ /**
57
+ * Format an idempotency key into the HTTP header object the control-plane
58
+ * expects. Pairs with {@link idempotencyKey} to keep the header name in
59
+ * exactly one place.
60
+ *
61
+ * The header is emitted lowercase to match HTTP/2 on-wire form and the
62
+ * existing SDK convention used by the module-internal helpers.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * const key = idempotencyKey("task-claim:task_123");
67
+ * await fetch(url, { headers: { ...idempotencyHeader(key), ...auth } });
68
+ * ```
69
+ */
70
+ export declare function idempotencyHeader(key: string): {
71
+ "idempotency-key": string;
72
+ };
73
+ /**
74
+ * Run `fn` with retry, exponential backoff, and jitter.
75
+ *
76
+ * Retries only when the raised error is a retryable {@link ShardLinkError}.
77
+ * Respects `error.retryAfter` (from `Retry-After` header) when present.
78
+ *
79
+ * @example
80
+ * ```ts
81
+ * const result = await withRetry(
82
+ * () => tasks.claim("task_123"),
83
+ * { maxAttempts: 5, baseDelay: 500 }
84
+ * );
85
+ * ```
86
+ */
87
+ export declare function withRetry<T>(fn: () => Promise<T>, overrides?: Partial<RetryPolicy>): Promise<T>;
88
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,iDAAiD;AACjD,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE;IACpC,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAC;CACrB,KAAK,IAAI,CAAC;AAEX,2CAA2C;AAC3C,MAAM,WAAW,WAAW;IAC1B,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED,8DAA8D;AAC9D,eAAO,MAAM,aAAa,EAAE,WAK3B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOrD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAE5E;AAuDD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,SAAS,GAAE,OAAO,CAAC,WAAW,CAAM,GACnC,OAAO,CAAC,CAAC,CAAC,CAgCZ"}
package/dist/retry.js ADDED
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Smart retry policies and idempotency-key helpers.
3
+ *
4
+ * The default policy only retries errors the control-plane marked as
5
+ * retryable, respects server-supplied `Retry-After`, and adds jitter so
6
+ * independent clients don't synchronise on a thundering herd.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ import { RateLimitError, ServerError, NetworkError, ShardLinkError } from "./errors.js";
11
+ /** Reasonable defaults — safe for any idempotent mutation. */
12
+ export const DEFAULT_RETRY = {
13
+ maxAttempts: 3,
14
+ baseDelay: 1_000,
15
+ maxDelay: 30_000,
16
+ jitter: 0.2
17
+ };
18
+ /**
19
+ * Generate an idempotency key suitable for HTTP `Idempotency-Key` headers.
20
+ *
21
+ * @param prefix - A stable prefix identifying the logical operation.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * const key = idempotencyKey("task-claim:task_123");
26
+ * // → "task-claim:task_123:01J...Z"
27
+ * ```
28
+ */
29
+ export function idempotencyKey(prefix) {
30
+ const trimmed = prefix.trim().replace(/[:\s]+$/u, "");
31
+ const uuid = typeof globalThis.crypto?.randomUUID === "function"
32
+ ? globalThis.crypto.randomUUID()
33
+ : fallbackRandom();
34
+ return `${trimmed}:${uuid}`;
35
+ }
36
+ /**
37
+ * Format an idempotency key into the HTTP header object the control-plane
38
+ * expects. Pairs with {@link idempotencyKey} to keep the header name in
39
+ * exactly one place.
40
+ *
41
+ * The header is emitted lowercase to match HTTP/2 on-wire form and the
42
+ * existing SDK convention used by the module-internal helpers.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * const key = idempotencyKey("task-claim:task_123");
47
+ * await fetch(url, { headers: { ...idempotencyHeader(key), ...auth } });
48
+ * ```
49
+ */
50
+ export function idempotencyHeader(key) {
51
+ return { "idempotency-key": key };
52
+ }
53
+ function fallbackRandom() {
54
+ const bytes = new Array(16)
55
+ .fill(0)
56
+ .map(() => Math.floor(Math.random() * 256)
57
+ .toString(16)
58
+ .padStart(2, "0"))
59
+ .join("");
60
+ return `${bytes.slice(0, 8)}-${bytes.slice(8, 12)}-${bytes.slice(12, 16)}-${bytes.slice(16, 20)}-${bytes.slice(20)}`;
61
+ }
62
+ function sleep(ms, signal) {
63
+ return new Promise((resolve, reject) => {
64
+ if (signal?.aborted) {
65
+ reject(new Error("aborted"));
66
+ return;
67
+ }
68
+ const handle = setTimeout(() => {
69
+ signal?.removeEventListener("abort", onAbort);
70
+ resolve();
71
+ }, ms);
72
+ const onAbort = () => {
73
+ clearTimeout(handle);
74
+ reject(new Error("aborted"));
75
+ };
76
+ signal?.addEventListener("abort", onAbort, { once: true });
77
+ });
78
+ }
79
+ function computeDelay(attempt, policy, errorRetryAfter) {
80
+ const exponential = Math.min(policy.maxDelay, policy.baseDelay * 2 ** (attempt - 1));
81
+ const jitterAmount = exponential * policy.jitter * Math.random();
82
+ const backoff = Math.round(exponential + jitterAmount);
83
+ if (errorRetryAfter !== undefined) {
84
+ return Math.max(errorRetryAfter, backoff);
85
+ }
86
+ return backoff;
87
+ }
88
+ function shouldRetry(error, policy) {
89
+ if (!(error instanceof ShardLinkError)) {
90
+ return false;
91
+ }
92
+ if (policy.retryOn && policy.retryOn.length > 0) {
93
+ return policy.retryOn.includes(error.code);
94
+ }
95
+ if (error instanceof RateLimitError)
96
+ return true;
97
+ if (error instanceof ServerError)
98
+ return true;
99
+ if (error instanceof NetworkError)
100
+ return true;
101
+ return error.retryable;
102
+ }
103
+ /**
104
+ * Run `fn` with retry, exponential backoff, and jitter.
105
+ *
106
+ * Retries only when the raised error is a retryable {@link ShardLinkError}.
107
+ * Respects `error.retryAfter` (from `Retry-After` header) when present.
108
+ *
109
+ * @example
110
+ * ```ts
111
+ * const result = await withRetry(
112
+ * () => tasks.claim("task_123"),
113
+ * { maxAttempts: 5, baseDelay: 500 }
114
+ * );
115
+ * ```
116
+ */
117
+ export async function withRetry(fn, overrides = {}) {
118
+ const policy = { ...DEFAULT_RETRY, ...overrides };
119
+ let lastError;
120
+ for (let attempt = 1; attempt <= policy.maxAttempts; attempt += 1) {
121
+ if (policy.signal?.aborted) {
122
+ throw new Error("aborted");
123
+ }
124
+ try {
125
+ return await fn();
126
+ }
127
+ catch (error) {
128
+ lastError = error;
129
+ if (attempt === policy.maxAttempts || !shouldRetry(error, policy)) {
130
+ throw error;
131
+ }
132
+ const retryAfter = error instanceof ShardLinkError ? error.retryAfter : undefined;
133
+ const delay = computeDelay(attempt, policy, retryAfter);
134
+ if (policy.onAttempt) {
135
+ try {
136
+ policy.onAttempt({
137
+ attempt,
138
+ error,
139
+ delayMs: delay,
140
+ maxAttempts: policy.maxAttempts
141
+ });
142
+ }
143
+ catch {
144
+ // Observability hook failures must never break the retry loop.
145
+ }
146
+ }
147
+ await sleep(delay, policy.signal);
148
+ }
149
+ }
150
+ throw lastError;
151
+ }
152
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"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"}