@dxos/edge-client 0.8.4-main.dedc0f3 → 0.8.4-main.dfabb4ec29

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 (50) hide show
  1. package/dist/lib/{browser/chunk-IKP53CBQ.mjs → neutral/chunk-ZIQ5T3A7.mjs} +20 -83
  2. package/dist/lib/{browser/chunk-IKP53CBQ.mjs.map → neutral/chunk-ZIQ5T3A7.mjs.map} +2 -2
  3. package/dist/lib/{browser → neutral}/edge-ws-muxer.mjs +1 -1
  4. package/dist/lib/{browser → neutral}/index.mjs +378 -439
  5. package/dist/lib/neutral/index.mjs.map +7 -0
  6. package/dist/lib/neutral/meta.json +1 -0
  7. package/dist/lib/{browser → neutral}/testing/index.mjs +6 -31
  8. package/dist/lib/neutral/testing/index.mjs.map +7 -0
  9. package/dist/types/src/auth.d.ts.map +1 -1
  10. package/dist/types/src/edge-client.d.ts +5 -2
  11. package/dist/types/src/edge-client.d.ts.map +1 -1
  12. package/dist/types/src/edge-http-client.d.ts +69 -30
  13. package/dist/types/src/edge-http-client.d.ts.map +1 -1
  14. package/dist/types/src/edge-identity.d.ts.map +1 -1
  15. package/dist/types/src/edge-ws-connection.d.ts +20 -0
  16. package/dist/types/src/edge-ws-connection.d.ts.map +1 -1
  17. package/dist/types/src/edge-ws-muxer.d.ts.map +1 -1
  18. package/dist/types/src/errors.d.ts.map +1 -1
  19. package/dist/types/src/http-client.d.ts +10 -7
  20. package/dist/types/src/http-client.d.ts.map +1 -1
  21. package/dist/types/src/protocol.d.ts +1 -1
  22. package/dist/types/src/protocol.d.ts.map +1 -1
  23. package/dist/types/src/testing/test-server.d.ts.map +1 -1
  24. package/dist/types/src/testing/test-utils.d.ts +3 -3
  25. package/dist/types/src/testing/test-utils.d.ts.map +1 -1
  26. package/dist/types/src/utils.d.ts +1 -1
  27. package/dist/types/src/utils.d.ts.map +1 -1
  28. package/dist/types/tsconfig.tsbuildinfo +1 -1
  29. package/package.json +28 -31
  30. package/src/edge-client.test.ts +20 -15
  31. package/src/edge-client.ts +55 -8
  32. package/src/edge-http-client.test.ts +3 -2
  33. package/src/edge-http-client.ts +226 -78
  34. package/src/edge-ws-connection.ts +120 -6
  35. package/src/http-client.test.ts +9 -6
  36. package/src/http-client.ts +18 -8
  37. package/src/testing/test-utils.ts +7 -7
  38. package/dist/lib/browser/index.mjs.map +0 -7
  39. package/dist/lib/browser/meta.json +0 -1
  40. package/dist/lib/browser/testing/index.mjs.map +0 -7
  41. package/dist/lib/node-esm/chunk-DR5YNW5K.mjs +0 -332
  42. package/dist/lib/node-esm/chunk-DR5YNW5K.mjs.map +0 -7
  43. package/dist/lib/node-esm/edge-ws-muxer.mjs +0 -12
  44. package/dist/lib/node-esm/edge-ws-muxer.mjs.map +0 -7
  45. package/dist/lib/node-esm/index.mjs +0 -1251
  46. package/dist/lib/node-esm/index.mjs.map +0 -7
  47. package/dist/lib/node-esm/meta.json +0 -1
  48. package/dist/lib/node-esm/testing/index.mjs +0 -186
  49. package/dist/lib/node-esm/testing/index.mjs.map +0 -7
  50. /package/dist/lib/{browser → neutral}/edge-ws-muxer.mjs.map +0 -0
@@ -6,7 +6,7 @@ import {
6
6
  getTypename,
7
7
  protocol,
8
8
  toUint8Array
9
- } from "./chunk-IKP53CBQ.mjs";
9
+ } from "./chunk-ZIQ5T3A7.mjs";
10
10
 
11
11
  // src/index.ts
12
12
  export * from "@dxos/protocols/buf/dxos/edge/messenger_pb";
@@ -60,15 +60,7 @@ var createChainEdgeIdentity = async (signer, identityKey, peerKey, chain, creden
60
60
  identityKey: identityKey.toHex(),
61
61
  peerKey: peerKey.toHex(),
62
62
  presentCredentials: async ({ challenge }) => {
63
- invariant(chain, void 0, {
64
- F: __dxlog_file,
65
- L: 75,
66
- S: void 0,
67
- A: [
68
- "chain",
69
- ""
70
- ]
71
- });
63
+ invariant(chain, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 56, S: void 0, A: ["chain", ""] });
72
64
  return signPresentation({
73
65
  presentation: {
74
66
  credentials: credentialsToSign
@@ -123,7 +115,8 @@ var createStubEdgeIdentity = () => {
123
115
  };
124
116
 
125
117
  // src/edge-client.ts
126
- import { Event, PersistentLifecycle, Trigger, TriggerState, scheduleMicroTask } from "@dxos/async";
118
+ import { Event, PersistentLifecycle, Trigger, TriggerState, scheduleMicroTask, scheduleTaskInterval as scheduleTaskInterval2 } from "@dxos/async";
119
+ import { TRACE_SPAN_ATTRIBUTE } from "@dxos/context";
127
120
  import { Resource as Resource2 } from "@dxos/context";
128
121
  import { log as log2, logInfo as logInfo2 } from "@dxos/log";
129
122
  import { EdgeStatus } from "@dxos/protocols/proto/dxos/client/services";
@@ -133,35 +126,11 @@ import { invariant as invariant2 } from "@dxos/invariant";
133
126
  import { schema } from "@dxos/protocols/proto";
134
127
  var __dxlog_file2 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-identity.ts";
135
128
  var handleAuthChallenge = async (failedResponse, identity) => {
136
- invariant2(failedResponse.status === 401, void 0, {
137
- F: __dxlog_file2,
138
- L: 21,
139
- S: void 0,
140
- A: [
141
- "failedResponse.status === 401",
142
- ""
143
- ]
144
- });
129
+ invariant2(failedResponse.status === 401, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 7, S: void 0, A: ["failedResponse.status === 401", ""] });
145
130
  const headerValue = failedResponse.headers.get("Www-Authenticate");
146
- invariant2(headerValue?.startsWith("VerifiablePresentation challenge="), void 0, {
147
- F: __dxlog_file2,
148
- L: 24,
149
- S: void 0,
150
- A: [
151
- "headerValue?.startsWith('VerifiablePresentation challenge=')",
152
- ""
153
- ]
154
- });
131
+ invariant2(headerValue?.startsWith("VerifiablePresentation challenge="), void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 9, S: void 0, A: ["headerValue?.startsWith('VerifiablePresentation challenge=')", ""] });
155
132
  const challenge = headerValue?.slice("VerifiablePresentation challenge=".length);
156
- invariant2(challenge, void 0, {
157
- F: __dxlog_file2,
158
- L: 27,
159
- S: void 0,
160
- A: [
161
- "challenge",
162
- ""
163
- ]
164
- });
133
+ invariant2(challenge, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 11, S: void 0, A: ["challenge", ""] });
165
134
  const presentation = await identity.presentCredentials({
166
135
  challenge: Buffer.from(challenge, "base64")
167
136
  });
@@ -177,29 +146,38 @@ import { log, logInfo } from "@dxos/log";
177
146
  import { EdgeWebsocketProtocol } from "@dxos/protocols";
178
147
  import { buf } from "@dxos/protocols/buf";
179
148
  import { MessageSchema } from "@dxos/protocols/buf/dxos/edge/messenger_pb";
180
- function _define_property(obj, key, value) {
181
- if (key in obj) {
182
- Object.defineProperty(obj, key, {
183
- value,
184
- enumerable: true,
185
- configurable: true,
186
- writable: true
187
- });
188
- } else {
189
- obj[key] = value;
190
- }
191
- return obj;
192
- }
149
+ var __dxlog_file3 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-ws-connection.ts";
193
150
  function _ts_decorate(decorators, target, key, desc) {
194
151
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
195
152
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
196
153
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
197
154
  return c > 3 && r && Object.defineProperty(target, key, r), r;
198
155
  }
199
- var __dxlog_file3 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-ws-connection.ts";
200
156
  var SIGNAL_KEEPALIVE_INTERVAL = 4e3;
201
157
  var SIGNAL_KEEPALIVE_TIMEOUT = 12e3;
202
158
  var EdgeWsConnection = class extends Resource {
159
+ _identity;
160
+ _connectionInfo;
161
+ _callbacks;
162
+ _inactivityTimeoutCtx;
163
+ _ws;
164
+ _wsMuxer;
165
+ _lastReceivedMessageTimestamp = Date.now();
166
+ _openTimestamp;
167
+ // Latency tracking.
168
+ _pingTimestamp;
169
+ _rtt = 0;
170
+ // Rate tracking with sliding window.
171
+ _uploadRate = 0;
172
+ _downloadRate = 0;
173
+ _rateWindow = 1e4;
174
+ _rateUpdateInterval = 1e3;
175
+ _bytesSamples = [];
176
+ _messagesSent = 0;
177
+ _messagesReceived = 0;
178
+ constructor(_identity, _connectionInfo, _callbacks) {
179
+ super(), this._identity = _identity, this._connectionInfo = _connectionInfo, this._callbacks = _callbacks;
180
+ }
203
181
  get info() {
204
182
  return {
205
183
  open: this.isOpen,
@@ -207,34 +185,32 @@ var EdgeWsConnection = class extends Resource {
207
185
  device: this._identity.peerKey
208
186
  };
209
187
  }
188
+ get rtt() {
189
+ return this._rtt;
190
+ }
191
+ get uptime() {
192
+ return this._openTimestamp ? (Date.now() - this._openTimestamp) / 1e3 : 0;
193
+ }
194
+ get uploadRate() {
195
+ return this._uploadRate;
196
+ }
197
+ get downloadRate() {
198
+ return this._downloadRate;
199
+ }
200
+ get messagesSent() {
201
+ return this._messagesSent;
202
+ }
203
+ get messagesReceived() {
204
+ return this._messagesReceived;
205
+ }
210
206
  send(message) {
211
- invariant3(this._ws, void 0, {
212
- F: __dxlog_file3,
213
- L: 53,
214
- S: this,
215
- A: [
216
- "this._ws",
217
- ""
218
- ]
219
- });
220
- invariant3(this._wsMuxer, void 0, {
221
- F: __dxlog_file3,
222
- L: 54,
223
- S: this,
224
- A: [
225
- "this._wsMuxer",
226
- ""
227
- ]
228
- });
207
+ invariant3(this._ws, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 72, S: this, A: ["this._ws", ""] });
208
+ invariant3(this._wsMuxer, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 73, S: this, A: ["this._wsMuxer", ""] });
229
209
  log("sending...", {
230
210
  peerKey: this._identity.peerKey,
231
211
  payload: protocol.getPayloadType(message)
232
- }, {
233
- F: __dxlog_file3,
234
- L: 55,
235
- S: this,
236
- C: (f, a) => f(...a)
237
- });
212
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 74, S: this });
213
+ this._messagesSent++;
238
214
  if (this._ws?.protocol.includes(EdgeWebsocketProtocol.V0)) {
239
215
  const binary = buf.toBinary(MessageSchema, message);
240
216
  if (binary.length > CLOUDFLARE_MESSAGE_MAX_BYTES) {
@@ -242,22 +218,15 @@ var EdgeWsConnection = class extends Resource {
242
218
  byteLength: binary.byteLength,
243
219
  serviceId: message.serviceId,
244
220
  payload: protocol.getPayloadType(message)
245
- }, {
246
- F: __dxlog_file3,
247
- L: 59,
248
- S: this,
249
- C: (f, a) => f(...a)
250
- });
221
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 82, S: this });
251
222
  return;
252
223
  }
224
+ this._recordBytes(binary.byteLength, 0);
253
225
  this._ws.send(binary);
254
226
  } else {
255
- this._wsMuxer.send(message).catch((e) => log.catch(e, void 0, {
256
- F: __dxlog_file3,
257
- L: 68,
258
- S: this,
259
- C: (f, a) => f(...a)
260
- }));
227
+ const binary = buf.toBinary(MessageSchema, message);
228
+ this._recordBytes(binary.byteLength, 0);
229
+ this._wsMuxer.send(message).catch((e) => log.catch(e, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 95, S: this }));
261
230
  }
262
231
  }
263
232
  async _open() {
@@ -269,41 +238,30 @@ var EdgeWsConnection = class extends Resource {
269
238
  this._connectionInfo.protocolHeader
270
239
  ] : [
271
240
  ...baseProtocols
272
- ]);
241
+ ], this._connectionInfo.headers ? {
242
+ headers: this._connectionInfo.headers
243
+ } : void 0);
273
244
  const muxer = new WebSocketMuxer(this._ws);
274
245
  this._wsMuxer = muxer;
275
246
  this._ws.onopen = () => {
276
247
  if (this.isOpen) {
277
- log("connected", void 0, {
278
- F: __dxlog_file3,
279
- L: 85,
280
- S: this,
281
- C: (f, a) => f(...a)
282
- });
248
+ log("connected", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 114, S: this });
249
+ this._openTimestamp = Date.now();
283
250
  this._callbacks.onConnected();
284
251
  this._scheduleHeartbeats();
252
+ this._scheduleRateCalculation();
285
253
  } else {
286
254
  log.verbose("connected after becoming inactive", {
287
255
  currentIdentity: this._identity
288
- }, {
289
- F: __dxlog_file3,
290
- L: 89,
291
- S: this,
292
- C: (f, a) => f(...a)
293
- });
256
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 120, S: this });
294
257
  }
295
258
  };
296
259
  this._ws.onclose = (event) => {
297
260
  if (this.isOpen) {
298
- log.warn("disconnected while being open", {
261
+ log.warn("server disconnected", {
299
262
  code: event.code,
300
263
  reason: event.reason
301
- }, {
302
- F: __dxlog_file3,
303
- L: 94,
304
- S: this,
305
- C: (f, a) => f(...a)
306
- });
264
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 127, S: this });
307
265
  this._callbacks.onRestartRequired();
308
266
  muxer.destroy();
309
267
  }
@@ -313,56 +271,42 @@ var EdgeWsConnection = class extends Resource {
313
271
  log.warn("edge connection socket error", {
314
272
  error: event.error,
315
273
  info: event.message
316
- }, {
317
- F: __dxlog_file3,
318
- L: 101,
319
- S: this,
320
- C: (f, a) => f(...a)
321
- });
274
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 137, S: this });
322
275
  this._callbacks.onRestartRequired();
323
276
  } else {
324
277
  log.verbose("error ignored on closed connection", {
325
278
  error: event.error
326
- }, {
327
- F: __dxlog_file3,
328
- L: 104,
329
- S: this,
330
- C: (f, a) => f(...a)
331
- });
279
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 143, S: this });
332
280
  }
333
281
  };
334
282
  this._ws.onmessage = async (event) => {
335
283
  if (!this.isOpen) {
336
284
  log.verbose("message ignored on closed connection", {
337
285
  event: event.type
338
- }, {
339
- F: __dxlog_file3,
340
- L: 112,
341
- S: this,
342
- C: (f, a) => f(...a)
343
- });
286
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 152, S: this });
344
287
  return;
345
288
  }
346
289
  this._lastReceivedMessageTimestamp = Date.now();
347
290
  if (event.data === "__pong__") {
291
+ if (this._pingTimestamp) {
292
+ this._rtt = Date.now() - this._pingTimestamp;
293
+ this._pingTimestamp = void 0;
294
+ }
348
295
  this._rescheduleHeartbeatTimeout();
349
296
  return;
350
297
  }
351
298
  const bytes = await toUint8Array(event.data);
299
+ this._recordBytes(0, bytes.byteLength);
352
300
  if (!this.isOpen) {
353
301
  return;
354
302
  }
303
+ this._messagesReceived++;
355
304
  const message = this._ws?.protocol?.includes(EdgeWebsocketProtocol.V0) ? buf.fromBinary(MessageSchema, bytes) : muxer.receiveData(bytes);
356
305
  if (message) {
357
306
  log("received", {
358
307
  from: message.source,
359
308
  payload: protocol.getPayloadType(message)
360
- }, {
361
- F: __dxlog_file3,
362
- L: 130,
363
- S: this,
364
- C: (f, a) => f(...a)
365
- });
309
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 175, S: this });
366
310
  this._callbacks.onMessage(message);
367
311
  }
368
312
  };
@@ -379,29 +323,18 @@ var EdgeWsConnection = class extends Resource {
379
323
  if (err instanceof Error && err.message.includes("WebSocket is closed before the connection is established.")) {
380
324
  return;
381
325
  }
382
- log.warn("Error closing websocket", {
326
+ log.warn("error closing websocket", {
383
327
  err
384
- }, {
385
- F: __dxlog_file3,
386
- L: 148,
387
- S: this,
388
- C: (f, a) => f(...a)
389
- });
328
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 194, S: this });
390
329
  }
391
330
  }
392
331
  _scheduleHeartbeats() {
393
- invariant3(this._ws, void 0, {
394
- F: __dxlog_file3,
395
- L: 153,
396
- S: this,
397
- A: [
398
- "this._ws",
399
- ""
400
- ]
401
- });
332
+ invariant3(this._ws, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 200, S: this, A: ["this._ws", ""] });
402
333
  scheduleTaskInterval(this._ctx, async () => {
334
+ this._pingTimestamp = Date.now();
403
335
  this._ws?.send("__ping__");
404
336
  }, SIGNAL_KEEPALIVE_INTERVAL);
337
+ this._pingTimestamp = Date.now();
405
338
  this._ws.send("__ping__");
406
339
  this._rescheduleHeartbeatTimeout();
407
340
  }
@@ -410,21 +343,13 @@ var EdgeWsConnection = class extends Resource {
410
343
  return;
411
344
  }
412
345
  void this._inactivityTimeoutCtx?.dispose();
413
- this._inactivityTimeoutCtx = new Context(void 0, {
414
- F: __dxlog_file3,
415
- L: 172
416
- });
346
+ this._inactivityTimeoutCtx = new Context(void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 216 });
417
347
  scheduleTask(this._inactivityTimeoutCtx, () => {
418
348
  if (this.isOpen) {
419
349
  if (Date.now() - this._lastReceivedMessageTimestamp > SIGNAL_KEEPALIVE_TIMEOUT) {
420
350
  log.warn("restart due to inactivity timeout", {
421
351
  lastReceivedMessageTimestamp: this._lastReceivedMessageTimestamp
422
- }, {
423
- F: __dxlog_file3,
424
- L: 178,
425
- S: this,
426
- C: (f, a) => f(...a)
427
- });
352
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 220, S: this });
428
353
  this._callbacks.onRestartRequired();
429
354
  } else {
430
355
  this._rescheduleHeartbeatTimeout();
@@ -432,8 +357,46 @@ var EdgeWsConnection = class extends Resource {
432
357
  }
433
358
  }, SIGNAL_KEEPALIVE_TIMEOUT);
434
359
  }
435
- constructor(_identity, _connectionInfo, _callbacks) {
436
- super(), _define_property(this, "_identity", void 0), _define_property(this, "_connectionInfo", void 0), _define_property(this, "_callbacks", void 0), _define_property(this, "_inactivityTimeoutCtx", void 0), _define_property(this, "_ws", void 0), _define_property(this, "_wsMuxer", void 0), _define_property(this, "_lastReceivedMessageTimestamp", void 0), this._identity = _identity, this._connectionInfo = _connectionInfo, this._callbacks = _callbacks, this._lastReceivedMessageTimestamp = Date.now();
360
+ _recordBytes(sent, received) {
361
+ const now = Date.now();
362
+ const currentSecond = Math.floor(now / 1e3) * 1e3;
363
+ const existingSample = this._bytesSamples.find((s) => Math.floor(s.timestamp / 1e3) * 1e3 === currentSecond);
364
+ if (existingSample) {
365
+ existingSample.sent += sent;
366
+ existingSample.received += received;
367
+ } else {
368
+ this._bytesSamples.push({
369
+ timestamp: now,
370
+ sent,
371
+ received
372
+ });
373
+ }
374
+ }
375
+ _scheduleRateCalculation() {
376
+ scheduleTaskInterval(this._ctx, async () => {
377
+ this._calculateRates();
378
+ }, this._rateUpdateInterval);
379
+ this._calculateRates();
380
+ }
381
+ _calculateRates() {
382
+ const now = Date.now();
383
+ const cutoff = now - this._rateWindow;
384
+ this._bytesSamples = this._bytesSamples.filter((s) => s.timestamp > cutoff);
385
+ if (this._bytesSamples.length === 0) {
386
+ this._uploadRate = 0;
387
+ this._downloadRate = 0;
388
+ return;
389
+ }
390
+ let totalSent = 0;
391
+ let totalReceived = 0;
392
+ const oldestTimestamp = Math.min(...this._bytesSamples.map((s) => s.timestamp));
393
+ const timeSpan = (now - oldestTimestamp) / 1e3;
394
+ for (const sample of this._bytesSamples) {
395
+ totalSent += sample.sent;
396
+ totalReceived += sample.received;
397
+ }
398
+ this._uploadRate = timeSpan > 0 ? Math.round(totalSent / timeSpan) : 0;
399
+ this._downloadRate = timeSpan > 0 ? Math.round(totalReceived / timeSpan) : 0;
437
400
  }
438
401
  };
439
402
  _ts_decorate([
@@ -461,28 +424,34 @@ var getEdgeUrlWithProtocol = (baseUrl, protocol2) => {
461
424
  };
462
425
 
463
426
  // src/edge-client.ts
464
- function _define_property2(obj, key, value) {
465
- if (key in obj) {
466
- Object.defineProperty(obj, key, {
467
- value,
468
- enumerable: true,
469
- configurable: true,
470
- writable: true
471
- });
472
- } else {
473
- obj[key] = value;
474
- }
475
- return obj;
476
- }
427
+ var __dxlog_file4 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-client.ts";
477
428
  function _ts_decorate2(decorators, target, key, desc) {
478
429
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
479
430
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
480
431
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
481
432
  return c > 3 && r && Object.defineProperty(target, key, r), r;
482
433
  }
483
- var __dxlog_file4 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-client.ts";
484
434
  var DEFAULT_TIMEOUT = 1e4;
435
+ var STATUS_REFRESH_INTERVAL = 1e3;
485
436
  var EdgeClient = class extends Resource2 {
437
+ _identity;
438
+ _config;
439
+ statusChanged = new Event();
440
+ _persistentLifecycle = new PersistentLifecycle({
441
+ start: async () => this._connect(),
442
+ stop: async (state) => this._disconnect(state)
443
+ });
444
+ _messageListeners = /* @__PURE__ */ new Set();
445
+ _reconnectListeners = /* @__PURE__ */ new Set();
446
+ _baseWsUrl;
447
+ _baseHttpUrl;
448
+ _currentConnection = void 0;
449
+ _ready = new Trigger();
450
+ constructor(_identity, _config) {
451
+ super(), this._identity = _identity, this._config = _config;
452
+ this._baseWsUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "ws");
453
+ this._baseHttpUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "http");
454
+ }
486
455
  get info() {
487
456
  return {
488
457
  open: this.isOpen,
@@ -492,7 +461,15 @@ var EdgeClient = class extends Resource2 {
492
461
  };
493
462
  }
494
463
  get status() {
495
- return Boolean(this._currentConnection) && this._ready.state === TriggerState.RESOLVED ? EdgeStatus.CONNECTED : EdgeStatus.NOT_CONNECTED;
464
+ return {
465
+ state: Boolean(this._currentConnection) && this._ready.state === TriggerState.RESOLVED ? EdgeStatus.ConnectionState.CONNECTED : EdgeStatus.ConnectionState.NOT_CONNECTED,
466
+ uptime: this._currentConnection?.uptime ?? 0,
467
+ rtt: this._currentConnection?.rtt ?? 0,
468
+ rateBytesUp: this._currentConnection?.uploadRate ?? 0,
469
+ rateBytesDown: this._currentConnection?.downloadRate ?? 0,
470
+ messagesSent: this._currentConnection?.messagesSent ?? 0,
471
+ messagesReceived: this._currentConnection?.messagesReceived ?? 0
472
+ };
496
473
  }
497
474
  get identityKey() {
498
475
  return this._identity.identityKey;
@@ -505,12 +482,7 @@ var EdgeClient = class extends Resource2 {
505
482
  log2("Edge identity changed", {
506
483
  identity,
507
484
  oldIdentity: this._identity
508
- }, {
509
- F: __dxlog_file4,
510
- L: 99,
511
- S: this,
512
- C: (f, a) => f(...a)
513
- });
485
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 74, S: this });
514
486
  this._identity = identity;
515
487
  this._closeCurrentConnection(new EdgeIdentityChangedError());
516
488
  void this._persistentLifecycle.scheduleRestart();
@@ -520,14 +492,9 @@ var EdgeClient = class extends Resource2 {
520
492
  * Send message.
521
493
  * NOTE: The message is guaranteed to be delivered but the service must respond with a message to confirm processing.
522
494
  */
523
- async send(message) {
495
+ async send(ctx, message) {
524
496
  if (this._ready.state !== TriggerState.RESOLVED) {
525
- log2("waiting for websocket", void 0, {
526
- F: __dxlog_file4,
527
- L: 112,
528
- S: this,
529
- C: (f, a) => f(...a)
530
- });
497
+ log2("waiting for websocket", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 88, S: this });
531
498
  await this._ready.wait({
532
499
  timeout: this._config.timeout ?? DEFAULT_TIMEOUT
533
500
  });
@@ -538,6 +505,14 @@ var EdgeClient = class extends Resource2 {
538
505
  if (message.source && (message.source.peerKey !== this._identity.peerKey || message.source.identityKey !== this.identityKey)) {
539
506
  throw new EdgeIdentityChangedError();
540
507
  }
508
+ const traceCtx = ctx.getAttribute(TRACE_SPAN_ATTRIBUTE);
509
+ if (traceCtx) {
510
+ message.traceContext = {
511
+ $typeName: "dxos.edge.messenger.TraceContext",
512
+ traceparent: traceCtx.traceparent,
513
+ tracestate: traceCtx.tracestate
514
+ };
515
+ }
541
516
  this._currentConnection.send(message);
542
517
  }
543
518
  onMessage(listener) {
@@ -552,12 +527,7 @@ var EdgeClient = class extends Resource2 {
552
527
  try {
553
528
  listener();
554
529
  } catch (error) {
555
- log2.catch(error, void 0, {
556
- F: __dxlog_file4,
557
- L: 145,
558
- S: this,
559
- C: (f, a) => f(...a)
560
- });
530
+ log2.catch(error, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 123, S: this });
561
531
  }
562
532
  }
563
533
  });
@@ -570,22 +540,18 @@ var EdgeClient = class extends Resource2 {
570
540
  async _open() {
571
541
  log2("opening...", {
572
542
  info: this.info
573
- }, {
574
- F: __dxlog_file4,
575
- L: 158,
576
- S: this,
577
- C: (f, a) => f(...a)
578
- });
543
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 133, S: this });
579
544
  this._persistentLifecycle.open().catch((err) => {
580
545
  log2.warn("Error while opening connection", {
581
546
  err
582
- }, {
583
- F: __dxlog_file4,
584
- L: 160,
585
- S: this,
586
- C: (f, a) => f(...a)
587
- });
547
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 137, S: this });
588
548
  });
549
+ scheduleTaskInterval2(this._ctx, async () => {
550
+ if (!this._currentConnection) {
551
+ return;
552
+ }
553
+ this.statusChanged.emit(this.status);
554
+ }, STATUS_REFRESH_INTERVAL);
589
555
  }
590
556
  /**
591
557
  * Close connection and free resources.
@@ -593,12 +559,7 @@ var EdgeClient = class extends Resource2 {
593
559
  async _close() {
594
560
  log2("closing...", {
595
561
  peerKey: this._identity.peerKey
596
- }, {
597
- F: __dxlog_file4,
598
- L: 168,
599
- S: this,
600
- C: (f, a) => f(...a)
601
- });
562
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 152, S: this });
602
563
  this._closeCurrentConnection();
603
564
  await this._persistentLifecycle.close();
604
565
  }
@@ -610,12 +571,7 @@ var EdgeClient = class extends Resource2 {
610
571
  const path = `/ws/${identity.identityKey}/${identity.peerKey}`;
611
572
  const protocolHeader = this._config.disableAuth ? void 0 : await this._createAuthHeader(path);
612
573
  if (this._identity !== identity) {
613
- log2("identity changed during auth header request", void 0, {
614
- F: __dxlog_file4,
615
- L: 182,
616
- S: this,
617
- C: (f, a) => f(...a)
618
- });
574
+ log2("identity changed during auth header request", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 166, S: this });
619
575
  return void 0;
620
576
  }
621
577
  const restartRequired = new Trigger();
@@ -623,27 +579,20 @@ var EdgeClient = class extends Resource2 {
623
579
  log2("Opening websocket", {
624
580
  url: url.toString(),
625
581
  protocolHeader
626
- }, {
627
- F: __dxlog_file4,
628
- L: 188,
629
- S: this,
630
- C: (f, a) => f(...a)
631
- });
582
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 171, S: this });
632
583
  const connection = new EdgeWsConnection(identity, {
633
584
  url,
634
- protocolHeader
585
+ protocolHeader,
586
+ headers: this._config.clientTag ? {
587
+ "X-DXOS-Client-Tag": this._config.clientTag
588
+ } : void 0
635
589
  }, {
636
590
  onConnected: () => {
637
591
  if (this._isActive(connection)) {
638
592
  this._ready.wake();
639
593
  this._notifyReconnected();
640
594
  } else {
641
- log2.verbose("connected callback ignored, because connection is not active", void 0, {
642
- F: __dxlog_file4,
643
- L: 198,
644
- S: this,
645
- C: (f, a) => f(...a)
646
- });
595
+ log2.verbose("connected callback ignored, because connection is not active", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 187, S: this });
647
596
  }
648
597
  },
649
598
  onRestartRequired: () => {
@@ -651,12 +600,7 @@ var EdgeClient = class extends Resource2 {
651
600
  this._closeCurrentConnection();
652
601
  void this._persistentLifecycle.scheduleRestart();
653
602
  } else {
654
- log2.verbose("restart requested by inactive connection", void 0, {
655
- F: __dxlog_file4,
656
- L: 206,
657
- S: this,
658
- C: (f, a) => f(...a)
659
- });
603
+ log2.verbose("restart requested by inactive connection", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 195, S: this });
660
604
  }
661
605
  restartRequired.wake();
662
606
  },
@@ -667,12 +611,7 @@ var EdgeClient = class extends Resource2 {
667
611
  log2.verbose("ignored a message on inactive connection", {
668
612
  from: message.source,
669
613
  type: message.payload?.typeUrl
670
- }, {
671
- F: __dxlog_file4,
672
- L: 214,
673
- S: this,
674
- C: (f, a) => f(...a)
675
- });
614
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 203, S: this });
676
615
  }
677
616
  }
678
617
  });
@@ -704,12 +643,7 @@ var EdgeClient = class extends Resource2 {
704
643
  } catch (err) {
705
644
  log2.error("ws reconnect listener failed", {
706
645
  err
707
- }, {
708
- F: __dxlog_file4,
709
- L: 249,
710
- S: this,
711
- C: (f, a) => f(...a)
712
- });
646
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 238, S: this });
713
647
  }
714
648
  }
715
649
  }
@@ -721,12 +655,7 @@ var EdgeClient = class extends Resource2 {
721
655
  log2.error("ws incoming message processing failed", {
722
656
  err,
723
657
  payload: protocol.getPayloadType(message)
724
- }, {
725
- F: __dxlog_file4,
726
- L: 259,
727
- S: this,
728
- C: (f, a) => f(...a)
729
- });
658
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 249, S: this });
730
659
  }
731
660
  }
732
661
  }
@@ -742,23 +671,11 @@ var EdgeClient = class extends Resource2 {
742
671
  log2.warn("no auth challenge from edge", {
743
672
  status: response.status,
744
673
  statusText: response.statusText
745
- }, {
746
- F: __dxlog_file4,
747
- L: 271,
748
- S: this,
749
- C: (f, a) => f(...a)
750
- });
674
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 265, S: this });
751
675
  return void 0;
752
676
  }
753
677
  }
754
- constructor(_identity, _config) {
755
- super(), _define_property2(this, "_identity", void 0), _define_property2(this, "_config", void 0), _define_property2(this, "statusChanged", void 0), _define_property2(this, "_persistentLifecycle", void 0), _define_property2(this, "_messageListeners", void 0), _define_property2(this, "_reconnectListeners", void 0), _define_property2(this, "_baseWsUrl", void 0), _define_property2(this, "_baseHttpUrl", void 0), _define_property2(this, "_currentConnection", void 0), _define_property2(this, "_ready", void 0), _define_property2(this, "_isActive", void 0), this._identity = _identity, this._config = _config, this.statusChanged = new Event(), this._persistentLifecycle = new PersistentLifecycle({
756
- start: async () => this._connect(),
757
- stop: async (state) => this._disconnect(state)
758
- }), this._messageListeners = /* @__PURE__ */ new Set(), this._reconnectListeners = /* @__PURE__ */ new Set(), this._currentConnection = void 0, this._ready = new Trigger(), this._isActive = (connection) => connection === this._currentConnection;
759
- this._baseWsUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "ws");
760
- this._baseHttpUrl = getEdgeUrlWithProtocol(_config.socketEndpoint, "http");
761
- }
678
+ _isActive = (connection) => connection === this._currentConnection;
762
679
  };
763
680
  _ts_decorate2([
764
681
  logInfo2
@@ -769,44 +686,38 @@ var encodePresentationWsAuthHeader = (encodedPresentation) => {
769
686
  };
770
687
 
771
688
  // src/edge-http-client.ts
772
- import { FetchHttpClient, HttpClient } from "@effect/platform";
773
- import { Effect as Effect2, pipe } from "effect";
689
+ import * as FetchHttpClient from "@effect/platform/FetchHttpClient";
690
+ import * as HttpClient from "@effect/platform/HttpClient";
691
+ import * as Effect2 from "effect/Effect";
692
+ import * as Function from "effect/Function";
774
693
  import { sleep } from "@dxos/async";
775
- import { Context as Context3 } from "@dxos/context";
694
+ import { TRACE_SPAN_ATTRIBUTE as TRACE_SPAN_ATTRIBUTE2 } from "@dxos/context";
695
+ import { runAndForwardErrors } from "@dxos/effect";
696
+ import { invariant as invariant4 } from "@dxos/invariant";
776
697
  import { log as log4 } from "@dxos/log";
777
- import { EdgeAuthChallengeError, EdgeCallFailedError } from "@dxos/protocols";
698
+ import { EDGE_CLIENT_TAG_HEADER, EdgeAuthChallengeError, EdgeCallFailedError } from "@dxos/protocols";
778
699
  import { createUrl } from "@dxos/util";
779
700
 
780
701
  // src/http-client.ts
781
- import { Context as Context2, Duration, Effect, Layer, Schedule } from "effect";
702
+ import * as Context2 from "effect/Context";
703
+ import * as Duration from "effect/Duration";
704
+ import * as Effect from "effect/Effect";
705
+ import * as Layer from "effect/Layer";
706
+ import * as Schedule from "effect/Schedule";
782
707
  import { log as log3 } from "@dxos/log";
783
- function _define_property3(obj, key, value) {
784
- if (key in obj) {
785
- Object.defineProperty(obj, key, {
786
- value,
787
- enumerable: true,
788
- configurable: true,
789
- writable: true
790
- });
791
- } else {
792
- obj[key] = value;
793
- }
794
- return obj;
795
- }
796
708
  var __dxlog_file5 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/http-client.ts";
797
- var _Context_Tag;
798
- var HttpConfig = class extends (_Context_Tag = Context2.Tag("HttpConfig")()) {
709
+ var HttpConfig = class _HttpConfig extends Context2.Tag("HttpConfig")() {
710
+ static default = Layer.succeed(_HttpConfig, {
711
+ timeout: Duration.millis(1e3),
712
+ retryTimes: 3,
713
+ retryBaseDelay: Duration.millis(1e3)
714
+ });
799
715
  };
800
- _define_property3(HttpConfig, "default", Layer.succeed(HttpConfig, {
801
- timeout: Duration.millis(1e3),
802
- retryTimes: 3,
803
- retryBaseDelay: Duration.millis(1e3)
804
- }));
805
- var withRetry = (effect, { timeout = Duration.millis(1e3), retryBaseDelay = Duration.millis(1e3), retryTimes = 3 } = {}) => {
716
+ var withRetry = (effect, { timeout: timeout2 = Duration.millis(1e3), retryBaseDelay = Duration.millis(1e3), retryTimes = 3 } = {}) => {
806
717
  return effect.pipe(Effect.flatMap((res) => (
807
718
  // Treat 500 errors as retryable?
808
719
  res.status === 500 ? Effect.fail(new Error(res.status.toString())) : res.json
809
- )), Effect.timeout(timeout), Effect.retry({
720
+ )), Effect.timeout(timeout2), Effect.retry({
810
721
  schedule: Schedule.exponential(retryBaseDelay).pipe(Schedule.jittered),
811
722
  times: retryTimes
812
723
  }));
@@ -815,39 +726,37 @@ var withRetryConfig = (effect) => Effect.gen(function* () {
815
726
  const config = yield* HttpConfig;
816
727
  return yield* withRetry(effect, config);
817
728
  });
818
- var withLogging = (effect) => effect.pipe(Effect.tap((res) => log3.info("response", {
819
- status: res.status
820
- }, {
821
- F: __dxlog_file5,
822
- L: 58,
823
- S: void 0,
824
- C: (f, a) => f(...a)
825
- })));
729
+ var withLogging = (effect) => effect.pipe(Effect.tap((res) => {
730
+ log3.info("response", {
731
+ status: res.status
732
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 31, S: void 0 });
733
+ }));
826
734
  var encodeAuthHeader = (challenge) => {
827
735
  const encodedChallenge = Buffer.from(challenge).toString("base64");
828
736
  return `VerifiablePresentation pb;base64,${encodedChallenge}`;
829
737
  };
830
738
 
831
739
  // src/edge-http-client.ts
832
- function _define_property4(obj, key, value) {
833
- if (key in obj) {
834
- Object.defineProperty(obj, key, {
835
- value,
836
- enumerable: true,
837
- configurable: true,
838
- writable: true
839
- });
840
- } else {
841
- obj[key] = value;
842
- }
843
- return obj;
844
- }
845
740
  var __dxlog_file6 = "/__w/dxos/dxos/packages/core/mesh/edge-client/src/edge-http-client.ts";
846
741
  var DEFAULT_RETRY_TIMEOUT = 1500;
847
742
  var DEFAULT_RETRY_JITTER = 500;
848
743
  var DEFAULT_MAX_RETRIES_COUNT = 3;
849
744
  var WARNING_BODY_SIZE = 10 * 1024 * 1024;
850
745
  var EdgeHttpClient = class {
746
+ _baseUrl;
747
+ _clientTag;
748
+ _edgeIdentity;
749
+ /**
750
+ * Auth header is cached until receiving the next 401 from EDGE, at which point it gets refreshed.
751
+ */
752
+ _authHeader;
753
+ constructor(baseUrl, options) {
754
+ this._baseUrl = getEdgeUrlWithProtocol(baseUrl, "http");
755
+ this._clientTag = options?.clientTag;
756
+ log4("created", {
757
+ url: this._baseUrl
758
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 32, S: this });
759
+ }
851
760
  get baseUrl() {
852
761
  return this._baseUrl;
853
762
  }
@@ -860,24 +769,25 @@ var EdgeHttpClient = class {
860
769
  //
861
770
  // Status
862
771
  //
863
- async getStatus(args) {
864
- return this._call(new URL("/status", this.baseUrl), {
772
+ async getStatus(ctx, args) {
773
+ return this._call(ctx, new URL("/status", this.baseUrl), {
865
774
  ...args,
866
- method: "GET"
775
+ method: "GET",
776
+ auth: true
867
777
  });
868
778
  }
869
779
  //
870
780
  // Agents
871
781
  //
872
- createAgent(body, args) {
873
- return this._call(new URL("/agents/create", this.baseUrl), {
782
+ createAgent(ctx, body, args) {
783
+ return this._call(ctx, new URL("/agents/create", this.baseUrl), {
874
784
  ...args,
875
785
  method: "POST",
876
786
  body
877
787
  });
878
788
  }
879
- getAgentStatus(request, args) {
880
- return this._call(new URL(`/users/${request.ownerIdentityKey.toHex()}/agent/status`, this.baseUrl), {
789
+ getAgentStatus(ctx, request, args) {
790
+ return this._call(ctx, new URL(`/users/${request.ownerIdentityKey.toHex()}/agent/status`, this.baseUrl), {
881
791
  ...args,
882
792
  method: "GET"
883
793
  });
@@ -885,14 +795,14 @@ var EdgeHttpClient = class {
885
795
  //
886
796
  // Credentials
887
797
  //
888
- getCredentialsForNotarization(spaceId, args) {
889
- return this._call(new URL(`/spaces/${spaceId}/notarization`, this.baseUrl), {
798
+ getCredentialsForNotarization(ctx, spaceId, args) {
799
+ return this._call(ctx, new URL(`/spaces/${spaceId}/notarization`, this.baseUrl), {
890
800
  ...args,
891
801
  method: "GET"
892
802
  });
893
803
  }
894
- async notarizeCredentials(spaceId, body, args) {
895
- await this._call(new URL(`/spaces/${spaceId}/notarization`, this.baseUrl), {
804
+ async notarizeCredentials(ctx, spaceId, body, args) {
805
+ await this._call(ctx, new URL(`/spaces/${spaceId}/notarization`, this.baseUrl), {
896
806
  ...args,
897
807
  body,
898
808
  method: "POST"
@@ -901,8 +811,8 @@ var EdgeHttpClient = class {
901
811
  //
902
812
  // Identity
903
813
  //
904
- async recoverIdentity(body, args) {
905
- return this._call(new URL("/identity/recover", this.baseUrl), {
814
+ async recoverIdentity(ctx, body, args) {
815
+ return this._call(ctx, new URL("/identity/recover", this.baseUrl), {
906
816
  ...args,
907
817
  body,
908
818
  method: "POST"
@@ -911,8 +821,8 @@ var EdgeHttpClient = class {
911
821
  //
912
822
  // Invitations
913
823
  //
914
- async joinSpaceByInvitation(spaceId, body, args) {
915
- return this._call(new URL(`/spaces/${spaceId}/join`, this.baseUrl), {
824
+ async joinSpaceByInvitation(ctx, spaceId, body, args) {
825
+ return this._call(ctx, new URL(`/spaces/${spaceId}/join`, this.baseUrl), {
916
826
  ...args,
917
827
  body,
918
828
  method: "POST"
@@ -921,8 +831,8 @@ var EdgeHttpClient = class {
921
831
  //
922
832
  // OAuth and credentials
923
833
  //
924
- async initiateOAuthFlow(body, args) {
925
- return this._call(new URL("/oauth/initiate", this.baseUrl), {
834
+ async initiateOAuthFlow(ctx, body, args) {
835
+ return this._call(ctx, new URL("/oauth/initiate", this.baseUrl), {
926
836
  ...args,
927
837
  body,
928
838
  method: "POST"
@@ -931,8 +841,8 @@ var EdgeHttpClient = class {
931
841
  //
932
842
  // Spaces
933
843
  //
934
- async createSpace(body, args) {
935
- return this._call(new URL("/spaces/create", this.baseUrl), {
844
+ async createSpace(ctx, body, args) {
845
+ return this._call(ctx, new URL("/spaces/create", this.baseUrl), {
936
846
  ...args,
937
847
  body,
938
848
  method: "POST"
@@ -941,9 +851,10 @@ var EdgeHttpClient = class {
941
851
  //
942
852
  // Queues
943
853
  //
944
- async queryQueue(subspaceTag, spaceId, query, args) {
945
- const { queueId } = query;
946
- return this._call(createUrl(new URL(`/spaces/${subspaceTag}/${spaceId}/queue/${queueId}/query`, this.baseUrl), {
854
+ async queryQueue(ctx, subspaceTag, spaceId, query, args) {
855
+ const queueId = query.queueIds?.[0];
856
+ invariant4(queueId, "queueId required", { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 132, S: this, A: ["queueId", "'queueId required'"] });
857
+ return this._call(ctx, createUrl(new URL(`/spaces/${subspaceTag}/${spaceId}/queue/${queueId}/query`, this.baseUrl), {
947
858
  after: query.after,
948
859
  before: query.before,
949
860
  limit: query.limit,
@@ -954,8 +865,8 @@ var EdgeHttpClient = class {
954
865
  method: "GET"
955
866
  });
956
867
  }
957
- async insertIntoQueue(subspaceTag, spaceId, queueId, objects, args) {
958
- return this._call(new URL(`/spaces/${subspaceTag}/${spaceId}/queue/${queueId}`, this.baseUrl), {
868
+ async insertIntoQueue(ctx, subspaceTag, spaceId, queueId, objects, args) {
869
+ return this._call(ctx, new URL(`/spaces/${subspaceTag}/${spaceId}/queue/${queueId}`, this.baseUrl), {
959
870
  ...args,
960
871
  body: {
961
872
  objects
@@ -963,8 +874,8 @@ var EdgeHttpClient = class {
963
874
  method: "POST"
964
875
  });
965
876
  }
966
- async deleteFromQueue(subspaceTag, spaceId, queueId, objectIds, args) {
967
- return this._call(createUrl(new URL(`/spaces/${subspaceTag}/${spaceId}/queue/${queueId}`, this.baseUrl), {
877
+ async deleteFromQueue(ctx, subspaceTag, spaceId, queueId, objectIds, args) {
878
+ return this._call(ctx, createUrl(new URL(`/spaces/${subspaceTag}/${spaceId}/queue/${queueId}`, this.baseUrl), {
968
879
  ids: objectIds.join(",")
969
880
  }), {
970
881
  ...args,
@@ -974,12 +885,13 @@ var EdgeHttpClient = class {
974
885
  //
975
886
  // Functions
976
887
  //
977
- async uploadFunction(pathParts, body, args) {
888
+ async uploadFunction(ctx, pathParts, body, args) {
978
889
  const formData = new FormData();
979
890
  formData.append("name", body.name ?? "");
980
891
  formData.append("version", body.version);
981
892
  formData.append("ownerPublicKey", body.ownerPublicKey);
982
893
  formData.append("entryPoint", body.entryPoint);
894
+ body.runtime && formData.append("runtime", body.runtime);
983
895
  for (const [filename, content] of Object.entries(body.assets)) {
984
896
  formData.append("assets", new Blob([
985
897
  content
@@ -993,20 +905,20 @@ var EdgeHttpClient = class {
993
905
  pathParts.functionId
994
906
  ] : []
995
907
  ].join("/");
996
- return this._call(new URL(path, this.baseUrl), {
908
+ return this._call(ctx, new URL(path, this.baseUrl), {
997
909
  ...args,
998
910
  body: formData,
999
911
  method: "PUT",
1000
912
  json: false
1001
913
  });
1002
914
  }
1003
- async listFunctions(args) {
1004
- return this._call(new URL("/functions", this.baseUrl), {
915
+ async listFunctions(ctx, args) {
916
+ return this._call(ctx, new URL("/functions", this.baseUrl), {
1005
917
  ...args,
1006
918
  method: "GET"
1007
919
  });
1008
920
  }
1009
- async invokeFunction(params, input, args) {
921
+ async invokeFunction(ctx, params, input, args) {
1010
922
  const url = new URL(`/functions/${params.functionId}`, this.baseUrl);
1011
923
  if (params.version) {
1012
924
  url.searchParams.set("version", params.version);
@@ -1020,18 +932,17 @@ var EdgeHttpClient = class {
1020
932
  if (params.subrequestsLimit) {
1021
933
  url.searchParams.set("subrequestsLimit", params.subrequestsLimit.toString());
1022
934
  }
1023
- return this._call(url, {
935
+ return this._call(ctx, url, {
1024
936
  ...args,
1025
937
  body: input,
1026
- method: "POST",
1027
- rawResponse: true
938
+ method: "POST"
1028
939
  });
1029
940
  }
1030
941
  //
1031
942
  // Workflows
1032
943
  //
1033
- async executeWorkflow(spaceId, graphId, input, args) {
1034
- return this._call(new URL(`/workflows/${spaceId}/${graphId}`, this.baseUrl), {
944
+ async executeWorkflow(ctx, spaceId, graphId, input, args) {
945
+ return this._call(ctx, new URL(`/workflows/${spaceId}/${graphId}`, this.baseUrl), {
1035
946
  ...args,
1036
947
  body: input,
1037
948
  method: "POST"
@@ -1040,23 +951,67 @@ var EdgeHttpClient = class {
1040
951
  //
1041
952
  // Triggers
1042
953
  //
1043
- async getCronTriggers(spaceId) {
1044
- return this._call(new URL(`/test/functions/${spaceId}/triggers/crons`, this.baseUrl), {
954
+ async getCronTriggers(ctx, spaceId) {
955
+ return this._call(ctx, new URL(`/functions/${spaceId}/triggers/crons`, this.baseUrl), {
956
+ method: "GET"
957
+ });
958
+ }
959
+ async forceRunCronTrigger(ctx, spaceId, triggerId) {
960
+ return this._call(ctx, new URL(`/functions/${spaceId}/triggers/crons/${triggerId}/run`, this.baseUrl), {
961
+ method: "POST"
962
+ });
963
+ }
964
+ //
965
+ // Query
966
+ //
967
+ /**
968
+ * Execute a QueryAST query against a space.
969
+ */
970
+ async execQuery(ctx, spaceId, body, args) {
971
+ return this._call(ctx, new URL(`/spaces/${spaceId}/exec-query`, this.baseUrl), {
972
+ ...args,
973
+ body,
974
+ method: "POST"
975
+ });
976
+ }
977
+ //
978
+ // Registry
979
+ //
980
+ /**
981
+ * Fetches the hydrated plugin directory from the Edge registry service.
982
+ * Unauthenticated; safe to call without an identity.
983
+ */
984
+ async getRegistryPlugins(ctx, args) {
985
+ return this._call(ctx, new URL("/registry/plugins", this.baseUrl), {
986
+ ...args,
987
+ method: "GET"
988
+ });
989
+ }
990
+ /**
991
+ * Fetches the available release versions for a given plugin repo. `repo` is the
992
+ * GitHub `owner/name` form; this method takes care of URL-encoding before issuing
993
+ * the request. Unauthenticated; same surface area as {@link getRegistryPlugins}.
994
+ *
995
+ * Versions are returned newest first, suitable for direct rendering in a picker.
996
+ */
997
+ async getRegistryPluginVersions(ctx, repo, args) {
998
+ return this._call(ctx, new URL(`/registry/plugins/${encodeURIComponent(repo)}/versions`, this.baseUrl), {
999
+ ...args,
1045
1000
  method: "GET"
1046
1001
  });
1047
1002
  }
1048
1003
  //
1049
1004
  // Import/Export space.
1050
1005
  //
1051
- async importBundle(spaceId, body, args) {
1052
- return this._call(new URL(`/spaces/${spaceId}/import`, this.baseUrl), {
1006
+ async importBundle(ctx, spaceId, body, args) {
1007
+ return this._call(ctx, new URL(`/spaces/${spaceId}/import`, this.baseUrl), {
1053
1008
  ...args,
1054
1009
  body,
1055
1010
  method: "PUT"
1056
1011
  });
1057
1012
  }
1058
- async exportBundle(spaceId, body, args) {
1059
- return this._call(new URL(`/spaces/${spaceId}/export`, this.baseUrl), {
1013
+ async exportBundle(ctx, spaceId, body, args) {
1014
+ return this._call(ctx, new URL(`/spaces/${spaceId}/export`, this.baseUrl), {
1060
1015
  ...args,
1061
1016
  body,
1062
1017
  method: "POST"
@@ -1065,78 +1020,67 @@ var EdgeHttpClient = class {
1065
1020
  //
1066
1021
  // Internal
1067
1022
  //
1068
- async _fetch(url, args) {
1069
- return pipe(HttpClient.get(url), withLogging, withRetryConfig, Effect2.provide(FetchHttpClient.layer), Effect2.provide(HttpConfig.default), Effect2.withSpan("EdgeHttpClient"), Effect2.runPromise);
1023
+ async _fetch(url, _args) {
1024
+ return Function.pipe(HttpClient.get(url), withLogging, withRetryConfig, Effect2.provide(FetchHttpClient.layer), Effect2.provide(HttpConfig.default), Effect2.withSpan("EdgeHttpClient"), runAndForwardErrors);
1070
1025
  }
1071
1026
  // TODO(burdon): Refactor with effect (see edge-http-client.test.ts).
1072
- async _call(url, args) {
1027
+ async _call(ctx, url, args) {
1073
1028
  const shouldRetry = createRetryHandler(args);
1074
- const requestContext = args.context ?? new Context3(void 0, {
1075
- F: __dxlog_file6,
1076
- L: 389
1077
- });
1078
1029
  log4("fetch", {
1079
1030
  url,
1080
1031
  request: args.body
1081
- }, {
1082
- F: __dxlog_file6,
1083
- L: 390,
1084
- S: this,
1085
- C: (f, a) => f(...a)
1086
- });
1032
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 302, S: this });
1033
+ const traceHeaders = getTraceHeaders(ctx);
1087
1034
  let handledAuth = false;
1035
+ const tryCount = 1;
1088
1036
  while (true) {
1089
1037
  let processingError = void 0;
1090
- let retryAfterHeaderValue = Number.NaN;
1091
1038
  try {
1092
- const request = createRequest(args, this._authHeader);
1039
+ if (!this._authHeader && args.auth) {
1040
+ const response2 = await fetch(new URL(`/auth`, this.baseUrl));
1041
+ if (response2.status === 401) {
1042
+ this._authHeader = await this._handleUnauthorized(response2);
1043
+ }
1044
+ }
1045
+ const request = createRequest(args, this._authHeader, traceHeaders, this._clientTag);
1046
+ log4("call edge", {
1047
+ url,
1048
+ tryCount,
1049
+ authHeader: !!this._authHeader
1050
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 319, S: this });
1093
1051
  const response = await fetch(url, request);
1094
- retryAfterHeaderValue = Number(response.headers.get("Retry-After"));
1095
1052
  if (response.ok) {
1096
- const body = await response.json();
1097
- if (args.rawResponse) {
1098
- return body;
1099
- }
1100
- if (!("success" in body)) {
1101
- return body;
1053
+ const body2 = await response.clone().json();
1054
+ invariant4(body2, "Expected body to be present", { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 327, S: this, A: ["body", "'Expected body to be present'"] });
1055
+ if (!("success" in body2)) {
1056
+ return body2;
1102
1057
  }
1103
- if (body.success) {
1104
- return body.data;
1105
- }
1106
- log4.warn("unsuccessful edge response", {
1107
- url,
1108
- body
1109
- }, {
1110
- F: __dxlog_file6,
1111
- L: 415,
1112
- S: this,
1113
- C: (f, a) => f(...a)
1114
- });
1115
- if (body.errorData?.type === "auth_challenge" && typeof body.errorData?.challenge === "string") {
1116
- processingError = new EdgeAuthChallengeError(body.errorData.challenge, body.errorData);
1117
- } else if (body.errorData) {
1118
- processingError = EdgeCallFailedError.fromUnsuccessfulResponse(response, body);
1058
+ if (body2.success) {
1059
+ return body2.data;
1119
1060
  }
1120
1061
  } else if (response.status === 401 && !handledAuth) {
1121
1062
  this._authHeader = await this._handleUnauthorized(response);
1122
1063
  handledAuth = true;
1123
1064
  continue;
1065
+ }
1066
+ const body = response.headers.get("Content-Type") === "application/json" ? await response.clone().json() : void 0;
1067
+ invariant4(!body?.success, "Expected body to not be a failure response or undefined.", { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 340, S: this, A: ["!body?.success", "'Expected body to not be a failure response or undefined.'"] });
1068
+ if (body?.data?.type === "auth_challenge" && typeof body?.data?.challenge === "string") {
1069
+ processingError = new EdgeAuthChallengeError(body.data.challenge, body.data);
1070
+ } else if (body?.success === false) {
1071
+ processingError = EdgeCallFailedError.fromUnsuccessfulResponse(response, body);
1124
1072
  } else {
1073
+ invariant4(!response.ok, "Expected response to not be ok.", { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 346, S: this, A: ["!response.ok", "'Expected response to not be ok.'"] });
1125
1074
  processingError = await EdgeCallFailedError.fromHttpFailure(response);
1126
1075
  }
1127
1076
  } catch (error) {
1128
1077
  processingError = EdgeCallFailedError.fromProcessingFailureCause(error);
1129
1078
  }
1130
- if (processingError?.isRetryable && await shouldRetry(requestContext, retryAfterHeaderValue)) {
1131
- log4("retrying edge request", {
1079
+ if (processingError?.isRetryable && await shouldRetry(ctx, processingError.retryAfterMs)) {
1080
+ log4.verbose("retrying edge request", {
1132
1081
  url,
1133
1082
  processingError
1134
- }, {
1135
- F: __dxlog_file6,
1136
- L: 433,
1137
- S: this,
1138
- C: (f, a) => f(...a)
1139
- });
1083
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 353, S: this });
1140
1084
  } else {
1141
1085
  throw processingError;
1142
1086
  }
@@ -1144,33 +1088,14 @@ var EdgeHttpClient = class {
1144
1088
  }
1145
1089
  async _handleUnauthorized(response) {
1146
1090
  if (!this._edgeIdentity) {
1147
- log4.warn("unauthorized response received before identity was set", void 0, {
1148
- F: __dxlog_file6,
1149
- L: 442,
1150
- S: this,
1151
- C: (f, a) => f(...a)
1152
- });
1091
+ log4.warn("unauthorized response received before identity was set", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 364, S: this });
1153
1092
  throw await EdgeCallFailedError.fromHttpFailure(response);
1154
1093
  }
1155
1094
  const challenge = await handleAuthChallenge(response, this._edgeIdentity);
1156
1095
  return encodeAuthHeader(challenge);
1157
1096
  }
1158
- constructor(baseUrl) {
1159
- _define_property4(this, "_baseUrl", void 0);
1160
- _define_property4(this, "_edgeIdentity", void 0);
1161
- _define_property4(this, "_authHeader", void 0);
1162
- this._baseUrl = getEdgeUrlWithProtocol(baseUrl, "http");
1163
- log4("created", {
1164
- url: this._baseUrl
1165
- }, {
1166
- F: __dxlog_file6,
1167
- L: 97,
1168
- S: this,
1169
- C: (f, a) => f(...a)
1170
- });
1171
- }
1172
1097
  };
1173
- var createRequest = ({ method, body, json = true }, authHeader) => {
1098
+ var createRequest = ({ method, body, json = true }, authHeader, traceHeaders, clientTag) => {
1174
1099
  let requestBody;
1175
1100
  const headers = {};
1176
1101
  if (json) {
@@ -1182,30 +1107,44 @@ var createRequest = ({ method, body, json = true }, authHeader) => {
1182
1107
  if (typeof requestBody === "string" && requestBody.length > WARNING_BODY_SIZE) {
1183
1108
  log4.warn("Request with large body", {
1184
1109
  bodySize: requestBody.length
1185
- }, {
1186
- F: __dxlog_file6,
1187
- L: 466,
1188
- S: void 0,
1189
- C: (f, a) => f(...a)
1190
- });
1110
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 381, S: void 0 });
1191
1111
  }
1192
1112
  if (authHeader) {
1193
1113
  headers["Authorization"] = authHeader;
1194
1114
  }
1115
+ if (traceHeaders) {
1116
+ Object.assign(headers, traceHeaders);
1117
+ }
1118
+ if (clientTag) {
1119
+ headers[EDGE_CLIENT_TAG_HEADER] = clientTag;
1120
+ }
1195
1121
  return {
1196
1122
  method,
1197
1123
  body: requestBody,
1198
1124
  headers
1199
1125
  };
1200
1126
  };
1201
- var createRetryHandler = ({ retry }) => {
1202
- if (!retry || retry.count < 1) {
1127
+ var getTraceHeaders = (ctx) => {
1128
+ const traceCtx = ctx.getAttribute(TRACE_SPAN_ATTRIBUTE2);
1129
+ if (!traceCtx) {
1130
+ return void 0;
1131
+ }
1132
+ const headers = {
1133
+ traceparent: traceCtx.traceparent
1134
+ };
1135
+ if (traceCtx.tracestate) {
1136
+ headers.tracestate = traceCtx.tracestate;
1137
+ }
1138
+ return headers;
1139
+ };
1140
+ var createRetryHandler = ({ retry: retry2 }) => {
1141
+ if (!retry2 || retry2.count < 1) {
1203
1142
  return async () => false;
1204
1143
  }
1205
1144
  let retries = 0;
1206
- const maxRetries = retry.count ?? DEFAULT_MAX_RETRIES_COUNT;
1207
- const baseTimeout = retry.timeout ?? DEFAULT_RETRY_TIMEOUT;
1208
- const jitter = retry.jitter ?? DEFAULT_RETRY_JITTER;
1145
+ const maxRetries = retry2.count ?? DEFAULT_MAX_RETRIES_COUNT;
1146
+ const baseTimeout = retry2.timeout ?? DEFAULT_RETRY_TIMEOUT;
1147
+ const jitter = retry2.jitter ?? DEFAULT_RETRY_JITTER;
1209
1148
  return async (ctx, retryAfter) => {
1210
1149
  if (++retries > maxRetries || ctx.disposed) {
1211
1150
  return false;
@@ -1213,8 +1152,8 @@ var createRetryHandler = ({ retry }) => {
1213
1152
  if (retryAfter) {
1214
1153
  await sleep(retryAfter);
1215
1154
  } else {
1216
- const timeout = baseTimeout + Math.random() * jitter;
1217
- await sleep(timeout);
1155
+ const timeout2 = baseTimeout + Math.random() * jitter;
1156
+ await sleep(timeout2);
1218
1157
  }
1219
1158
  return true;
1220
1159
  };