@naylence/agent-sdk 0.3.5-test.101 → 0.3.5-test.103

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.
@@ -15674,12 +15674,12 @@
15674
15674
  // --- END ENV SHIM ---
15675
15675
 
15676
15676
  // This file is auto-generated during build - do not edit manually
15677
- // Generated from package.json version: 0.3.6
15677
+ // Generated from package.json version: 0.3.6-test.108
15678
15678
  /**
15679
15679
  * The package version, injected at build time.
15680
15680
  * @internal
15681
15681
  */
15682
- const VERSION$1 = '0.3.6';
15682
+ const VERSION$1 = '0.3.6-test.108';
15683
15683
 
15684
15684
  /**
15685
15685
  * Fame protocol specific error classes with WebSocket close codes and proper inheritance.
@@ -17275,6 +17275,50 @@
17275
17275
  });
17276
17276
  }
17277
17277
 
17278
+ function isModuleNotFoundError(error) {
17279
+ if (!(error instanceof Error)) {
17280
+ return false;
17281
+ }
17282
+ const message = error.message || '';
17283
+ if (message.includes('Cannot find module') ||
17284
+ message.includes('ERR_MODULE_NOT_FOUND') ||
17285
+ message.includes('MODULE_NOT_FOUND')) {
17286
+ return true;
17287
+ }
17288
+ const code = error.code;
17289
+ if (typeof code === 'string') {
17290
+ return code === 'MODULE_NOT_FOUND' || code === 'ERR_MODULE_NOT_FOUND';
17291
+ }
17292
+ return false;
17293
+ }
17294
+ /**
17295
+ * Wraps a dynamic import loader and enriches "module not found" failures with an actionable error message.
17296
+ */
17297
+ async function safeImport(loader, dependencyNameOrOptions, maybeOptions) {
17298
+ const options = typeof dependencyNameOrOptions === 'string'
17299
+ ? { dependencyName: dependencyNameOrOptions, ...(maybeOptions ?? {}) }
17300
+ : dependencyNameOrOptions;
17301
+ const dependencyName = options.dependencyName;
17302
+ try {
17303
+ return await loader();
17304
+ }
17305
+ catch (error) {
17306
+ if (isModuleNotFoundError(error)) {
17307
+ const message = options.helpMessage ??
17308
+ `Missing optional dependency "${dependencyName}". Install it to enable this feature.`;
17309
+ const enrichedError = new Error(message);
17310
+ try {
17311
+ enrichedError.cause = error;
17312
+ }
17313
+ catch {
17314
+ // Ignore environments that do not support attaching a cause.
17315
+ }
17316
+ throw enrichedError;
17317
+ }
17318
+ throw error;
17319
+ }
17320
+ }
17321
+
17278
17322
  /**
17279
17323
  * flow_controller.ts - credit window management with cooperative back-pressure.
17280
17324
  *
@@ -18209,50 +18253,6 @@
18209
18253
  return SecretSource.normalize(value);
18210
18254
  }
18211
18255
 
18212
- function isModuleNotFoundError(error) {
18213
- if (!(error instanceof Error)) {
18214
- return false;
18215
- }
18216
- const message = error.message || '';
18217
- if (message.includes('Cannot find module') ||
18218
- message.includes('ERR_MODULE_NOT_FOUND') ||
18219
- message.includes('MODULE_NOT_FOUND')) {
18220
- return true;
18221
- }
18222
- const code = error.code;
18223
- if (typeof code === 'string') {
18224
- return code === 'MODULE_NOT_FOUND' || code === 'ERR_MODULE_NOT_FOUND';
18225
- }
18226
- return false;
18227
- }
18228
- /**
18229
- * Wraps a dynamic import loader and enriches "module not found" failures with an actionable error message.
18230
- */
18231
- async function safeImport(loader, dependencyNameOrOptions, maybeOptions) {
18232
- const options = typeof dependencyNameOrOptions === 'string'
18233
- ? { dependencyName: dependencyNameOrOptions, ...(maybeOptions ?? {}) }
18234
- : dependencyNameOrOptions;
18235
- const dependencyName = options.dependencyName;
18236
- try {
18237
- return await loader();
18238
- }
18239
- catch (error) {
18240
- if (isModuleNotFoundError(error)) {
18241
- const message = options.helpMessage ??
18242
- `Missing optional dependency "${dependencyName}". Install it to enable this feature.`;
18243
- const enrichedError = new Error(message);
18244
- try {
18245
- enrichedError.cause = error;
18246
- }
18247
- catch {
18248
- // Ignore environments that do not support attaching a cause.
18249
- }
18250
- throw enrichedError;
18251
- }
18252
- throw error;
18253
- }
18254
- }
18255
-
18256
18256
  const indexedDBConfigSchema = object({
18257
18257
  type: literal('IndexedDBStorageProvider')
18258
18258
  .default('IndexedDBStorageProvider'),
@@ -21831,9 +21831,6 @@
21831
21831
  this.ackDoneSince = new Map();
21832
21832
  this.replyDoneSince = new Map();
21833
21833
  this.pendingAckDispatches = new Set();
21834
- this.recentlyHandled = new Map();
21835
- this.recentlyHandledOrder = [];
21836
- this.recentlyHandledTtlMs = 60000;
21837
21834
  this.isPreparingToStop = false;
21838
21835
  this.shutdownRequestedAtMs = null;
21839
21836
  this.shutdownRetryGraceMs = 1000;
@@ -22055,22 +22052,6 @@
22055
22052
  }
22056
22053
  }
22057
22054
  else {
22058
- const wasRecentlyHandled = await this.lock.runExclusive(async () => this.wasRecentlyHandled(envelope.id));
22059
- if (wasRecentlyHandled) {
22060
- logger$12.debug('tracker_duplicate_envelope_recently_handled', {
22061
- envp_id: envelope.id,
22062
- });
22063
- return new TrackedEnvelope({
22064
- timeoutAtMs: 0,
22065
- overallTimeoutAtMs: 0,
22066
- expectedResponseType: envelope.rtype ?? FameResponseType.NONE,
22067
- createdAtMs: Date.now(),
22068
- status: EnvelopeStatus.HANDLED,
22069
- mailboxType: MailboxType.INBOX,
22070
- originalEnvelope: envelope,
22071
- serviceName: inboxName,
22072
- });
22073
- }
22074
22055
  tracked = new TrackedEnvelope({
22075
22056
  timeoutAtMs: 0,
22076
22057
  overallTimeoutAtMs: 0,
@@ -22092,12 +22073,8 @@
22092
22073
  async onEnvelopeHandled(envelope) {
22093
22074
  const inbox = this.ensureInbox();
22094
22075
  envelope.status = EnvelopeStatus.HANDLED;
22076
+ // Delete the envelope from inbox to prevent growth
22095
22077
  await inbox.delete(envelope.originalEnvelope.id);
22096
- await this.lock.runExclusive(async () => {
22097
- this.markRecentlyHandled(envelope.originalEnvelope.id);
22098
- });
22099
- // Preserve handled envelope to prevent duplicate redelivery during shutdown drains.
22100
- // await inbox.set(envelope.originalEnvelope.id, envelope);
22101
22078
  }
22102
22079
  async onEnvelopeHandleFailed(inboxName, envelope, context, error, isFinalFailure = false) {
22103
22080
  const inbox = this.ensureInbox();
@@ -22312,9 +22289,9 @@
22312
22289
  });
22313
22290
  await this.markDoneSince(this.replyFutures, trackedEnvelope.originalEnvelope.id, this.replyDoneSince);
22314
22291
  await this.markDoneSince(this.ackFutures, trackedEnvelope.originalEnvelope.id, this.ackDoneSince);
22315
- if (envelope.rtype && Boolean(envelope.rtype & FameResponseType.ACK)) {
22316
- await this.sendAck(envelope);
22317
- }
22292
+ // Note: ACK is already sent in onCorrelatedMessage (lines 655-657)
22293
+ // when the reply envelope is first delivered. No need to send it again here.
22294
+ // Removing this duplicate sendAck call fixes the duplicate DeliveryAck bug.
22318
22295
  for (const handler of this.eventHandlers) {
22319
22296
  await handler.onEnvelopeReplied?.(trackedEnvelope, envelope);
22320
22297
  }
@@ -22464,8 +22441,6 @@
22464
22441
  }
22465
22442
  this.streamDone.clear();
22466
22443
  this.correlationToEnvelope.clear();
22467
- this.recentlyHandled.clear();
22468
- this.recentlyHandledOrder.length = 0;
22469
22444
  return values;
22470
22445
  });
22471
22446
  for (const timer of timers) {
@@ -23047,39 +23022,6 @@
23047
23022
  this.pendingAckDispatches.delete(ackDispatch);
23048
23023
  }
23049
23024
  }
23050
- markRecentlyHandled(envelopeId) {
23051
- const now = Date.now();
23052
- this.recentlyHandled.set(envelopeId, now);
23053
- this.recentlyHandledOrder.push(envelopeId);
23054
- this.trimRecentlyHandled(now);
23055
- }
23056
- wasRecentlyHandled(envelopeId) {
23057
- const now = Date.now();
23058
- const timestamp = this.recentlyHandled.get(envelopeId);
23059
- if (timestamp === undefined) {
23060
- return false;
23061
- }
23062
- if (now - timestamp > this.recentlyHandledTtlMs) {
23063
- this.recentlyHandled.delete(envelopeId);
23064
- return false;
23065
- }
23066
- return true;
23067
- }
23068
- trimRecentlyHandled(now) {
23069
- while (this.recentlyHandledOrder.length > 0) {
23070
- const candidate = this.recentlyHandledOrder[0];
23071
- const timestamp = this.recentlyHandled.get(candidate);
23072
- if (timestamp === undefined) {
23073
- this.recentlyHandledOrder.shift();
23074
- continue;
23075
- }
23076
- if (now - timestamp <= this.recentlyHandledTtlMs) {
23077
- break;
23078
- }
23079
- this.recentlyHandled.delete(candidate);
23080
- this.recentlyHandledOrder.shift();
23081
- }
23082
- }
23083
23025
  getShutdownRetryDeferDelay(nowMs) {
23084
23026
  if (!this.isPreparingToStop || this.shutdownRequestedAtMs === null) {
23085
23027
  return null;
@@ -24652,6 +24594,7 @@
24652
24594
  local_node_id: this.localNodeId,
24653
24595
  target_node_id: this.targetNodeId ?? null,
24654
24596
  inbox_capacity: preferredCapacity,
24597
+ passive: config.passive ?? false,
24655
24598
  timestamp: new Date().toISOString(),
24656
24599
  });
24657
24600
  this.onMsg = (event) => {
@@ -25492,6 +25435,20 @@
25492
25435
  await connector.start(this.wrappedHandler);
25493
25436
  this.connector = connector;
25494
25437
  const callbackGrants = this.node.gatherSupportedCallbackGrants();
25438
+ logger$Z.debug('callback_grants_before_augmentation', {
25439
+ count: callbackGrants.length,
25440
+ types: callbackGrants.map(g => g.type),
25441
+ });
25442
+ // Check if we should create a broadcast callback grant before processing connection grants
25443
+ // This prevents adding duplicate broadcast grants
25444
+ const shouldAddBroadcastGrant = this.shouldAdvertiseBroadcastGrant(grant, callbackGrants);
25445
+ const broadcastCallbackGrant = shouldAddBroadcastGrant
25446
+ ? this.createBroadcastCallbackGrant(grant)
25447
+ : null;
25448
+ logger$Z.debug('broadcast_callback_grant_check', {
25449
+ should_add: shouldAddBroadcastGrant,
25450
+ grant_created: !!broadcastCallbackGrant,
25451
+ });
25495
25452
  // Include admission client's connection grants as callback grants
25496
25453
  // This ensures DirectAdmissionClient grants are available for grant selection
25497
25454
  if (welcome.frame.connectionGrants && Array.isArray(welcome.frame.connectionGrants)) {
@@ -25501,16 +25458,31 @@
25501
25458
  const isDuplicate = callbackGrants.some(existing => JSON.stringify(existing) === JSON.stringify(grant));
25502
25459
  if (!isDuplicate) {
25503
25460
  callbackGrants.push(grant);
25461
+ logger$Z.debug('added_connection_grant_as_callback', {
25462
+ type: grant.type,
25463
+ });
25464
+ }
25465
+ else {
25466
+ logger$Z.debug('skipped_duplicate_connection_grant', {
25467
+ type: grant.type,
25468
+ });
25504
25469
  }
25505
25470
  }
25506
25471
  }
25507
25472
  }
25508
- if (this.shouldAdvertiseBroadcastGrant(grant, callbackGrants)) {
25509
- const augmented = this.createBroadcastCallbackGrant(grant);
25510
- if (augmented) {
25511
- callbackGrants.push(augmented);
25512
- }
25473
+ // Add broadcast grant after connection grants to ensure we don't duplicate
25474
+ // any broadcast grants that may have been in connectionGrants
25475
+ if (broadcastCallbackGrant && this.shouldAdvertiseBroadcastGrant(grant, callbackGrants)) {
25476
+ callbackGrants.push(broadcastCallbackGrant);
25477
+ logger$Z.debug('added_broadcast_callback_grant');
25478
+ }
25479
+ else if (broadcastCallbackGrant) {
25480
+ logger$Z.debug('skipped_duplicate_broadcast_callback_grant');
25513
25481
  }
25482
+ logger$Z.debug('callback_grants_after_augmentation', {
25483
+ count: callbackGrants.length,
25484
+ types: callbackGrants.map(g => g.type),
25485
+ });
25514
25486
  const attachInfo = await this.attachClient.attach(this.node, this.outboundOriginType, connector, welcome.frame, this.wrappedHandler, this.getKeys() ?? undefined, callbackGrants);
25515
25487
  this.targetSystemId = attachInfo.targetSystemId ?? null;
25516
25488
  if (this.targetSystemId) {
@@ -27306,15 +27278,29 @@
27306
27278
  constructor(options = {}) {
27307
27279
  this.buffer = [];
27308
27280
  this.inHandshake = false;
27281
+ this.expectedSystemId = null;
27309
27282
  this.timeoutMs = options.timeoutMs ?? 10000;
27310
27283
  this.attachmentKeyValidator = options.attachmentKeyValidator;
27311
27284
  this.replicaStickinessManager = options.replicaStickinessManager ?? null;
27312
27285
  }
27313
27286
  async attach(node, originType, connector, welcomeFrame, finalHandler, keys, callbackGrants) {
27314
27287
  this.inHandshake = true;
27288
+ this.expectedSystemId = welcomeFrame.systemId;
27315
27289
  const interimHandler = async (envelope, context) => {
27316
27290
  if (this.inHandshake) {
27317
- this.buffer.push(envelope);
27291
+ // Filter: only buffer frames related to our systemId or frames without systemId info
27292
+ const frameSystemId = envelope.frame?.systemId;
27293
+ if (!frameSystemId || frameSystemId === this.expectedSystemId) {
27294
+ this.buffer.push(envelope);
27295
+ }
27296
+ else {
27297
+ // Silently ignore frames from other agents during concurrent handshakes
27298
+ logger$W.debug('handshake_ignoring_frame_from_different_system', {
27299
+ frame_type: envelope.frame.type,
27300
+ frame_system_id: frameSystemId,
27301
+ expected_system_id: this.expectedSystemId,
27302
+ });
27303
+ }
27318
27304
  return null;
27319
27305
  }
27320
27306
  return finalHandler(envelope, context);
@@ -27441,6 +27427,7 @@
27441
27427
  parent_id: ackFrame.targetSystemId,
27442
27428
  });
27443
27429
  this.inHandshake = false;
27430
+ this.expectedSystemId = null;
27444
27431
  await connector.replaceHandler(finalHandler);
27445
27432
  while (this.buffer.length > 0) {
27446
27433
  const bufferedEnvelope = this.buffer.shift();
@@ -27517,9 +27504,20 @@
27517
27504
  if (envelope.frame.type === 'NodeAttachAck') {
27518
27505
  return envelope;
27519
27506
  }
27520
- logger$W.error('unexpected_frame_during_handshake', {
27521
- frame_type: envelope.frame.type,
27522
- });
27507
+ // NodeAttach frames during handshake are expected in multi-agent scenarios
27508
+ // where multiple agents attach concurrently to the same channel
27509
+ if (envelope.frame.type === 'NodeAttach') {
27510
+ logger$W.debug('handshake_ignoring_concurrent_attach', {
27511
+ frame_type: envelope.frame.type,
27512
+ frame_system_id: envelope.frame?.systemId ?? 'unknown',
27513
+ });
27514
+ }
27515
+ else {
27516
+ // Other unexpected frames are still logged as errors
27517
+ logger$W.error('unexpected_frame_during_handshake', {
27518
+ frame_type: envelope.frame.type,
27519
+ });
27520
+ }
27523
27521
  }
27524
27522
  await delay$2(HANDSHAKE_POLL_INTERVAL_MS);
27525
27523
  }
@@ -43127,6 +43125,7 @@
43127
43125
  inboxCapacity,
43128
43126
  localNodeId,
43129
43127
  initialTargetNodeId: resolvedTarget,
43128
+ passive: normalized.passive,
43130
43129
  };
43131
43130
  const connector = new BroadcastChannelConnector(connectorConfig, baseConfig);
43132
43131
  if (options.authorization) {
@@ -43165,6 +43164,9 @@
43165
43164
  if (normalizedLocalNodeId) {
43166
43165
  normalized.localNodeId = normalizedLocalNodeId;
43167
43166
  }
43167
+ if (typeof candidate.passive === 'boolean') {
43168
+ normalized.passive = candidate.passive;
43169
+ }
43168
43170
  if (typeof candidate.flowControl === 'boolean') {
43169
43171
  normalized.flowControl = candidate.flowControl;
43170
43172
  }
@@ -44508,11 +44510,19 @@
44508
44510
  ? Math.floor(initialWindowCandidate)
44509
44511
  : undefined;
44510
44512
  const initialTargetNodeId = this._normalizeNodeId(targetCandidate) ?? targetSystemId;
44513
+ const passive = typeof passiveCandidate === 'boolean' ? passiveCandidate : true;
44514
+ logger$o.debug('broadcast_channel_listener_building_connector_config', {
44515
+ system_id: systemId,
44516
+ channel_name: channelName,
44517
+ passive,
44518
+ has_base_config: !!baseConfig,
44519
+ passive_candidate: passiveCandidate,
44520
+ });
44511
44521
  return {
44512
44522
  type: BROADCAST_CHANNEL_CONNECTOR_TYPE,
44513
44523
  channelName,
44514
44524
  inboxCapacity,
44515
- passive: typeof passiveCandidate === 'boolean' ? passiveCandidate : true,
44525
+ passive,
44516
44526
  initialWindow,
44517
44527
  localNodeId,
44518
44528
  initialTargetNodeId,