@bpmsoftwaresolutions/ai-engine-client 1.1.61 → 1.1.63

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +430 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bpmsoftwaresolutions/ai-engine-client",
3
- "version": "1.1.61",
3
+ "version": "1.1.63",
4
4
  "description": "Thin npm client for the AI Engine operator and retrieval APIs",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
package/src/index.js CHANGED
@@ -106,6 +106,31 @@ function normalizeMessageKind(value) {
106
106
  });
107
107
  }
108
108
 
109
+ function normalizeConnectionFirstMessageKind(value, transferKind) {
110
+ const text = cleanText(value);
111
+ if (!text) {
112
+ return normalizeMessageKind(transferKind === 'handoff' ? 'handoff' : 'request');
113
+ }
114
+ const normalized = text.toLowerCase();
115
+ const aliases = {
116
+ connection_request: 'request',
117
+ connection_accepted: 'response',
118
+ connection_acceptance: 'response',
119
+ handoff_request: 'handoff',
120
+ handoff_acceptance: 'response',
121
+ handoff_response: 'response',
122
+ acceptance: 'response',
123
+ decline: 'response',
124
+ };
125
+ const candidate = aliases[normalized] || text;
126
+ try {
127
+ return normalizeMessageKind(candidate);
128
+ } catch (error) {
129
+ void error;
130
+ return normalizeMessageKind(transferKind === 'handoff' ? 'handoff' : 'request');
131
+ }
132
+ }
133
+
109
134
  function normalizeTransferKind(value) {
110
135
  return normalizeEnum(value, AGENT_COMMUNICATION_TRANSFER_KINDS, 'upstream_remediation', 'transfer_kind', {
111
136
  remediation_request: 'upstream_remediation',
@@ -379,7 +404,7 @@ function buildEligibilityError(message, details = {}) {
379
404
  }
380
405
 
381
406
  export class AIEngineClient {
382
- constructor({ baseUrl, accessToken, tokenProvider, apiKey, clientId, actorId, fetchImpl, timeoutMs } = {}) {
407
+ constructor({ baseUrl, accessToken, tokenProvider, apiKey, clientId, actorId, agentSessionId, fetchImpl, timeoutMs } = {}) {
383
408
  if (!baseUrl) throw new Error('baseUrl is required.');
384
409
  this.baseUrl = trimTrailingSlash(baseUrl);
385
410
  this.accessToken = accessToken || null;
@@ -387,6 +412,7 @@ export class AIEngineClient {
387
412
  this.apiKey = apiKey || null;
388
413
  this.clientId = clientId || null;
389
414
  this.actorId = actorId || 'sdk:npm-ai-engine-client';
415
+ this.agentSessionId = cleanText(agentSessionId) || null;
390
416
  this.fetchImpl = fetchImpl || globalThis.fetch;
391
417
  this.timeoutMs = timeoutMs || DEFAULT_TIMEOUT_MS;
392
418
  this.clientVersion = AI_ENGINE_CLIENT_VERSION;
@@ -452,6 +478,12 @@ export class AIEngineClient {
452
478
  acceptTransferPacket: (request) => this.acceptCommunicationTransferPacket(request),
453
479
  closeTransferPacket: (request) => this.closeCommunicationTransferPacket(request),
454
480
  getTransferHealth: (request) => this.getCommunicationTransferHealth(request),
481
+ openAgentChannel: (request) => this.openAgentChannel(request),
482
+ acceptAgentChannel: (request) => this.acceptAgentChannel(request),
483
+ postAgentHeartbeat: (request) => this.postAgentHeartbeat(request),
484
+ postAgentMessage: (request) => this.postAgentMessage(request),
485
+ acknowledgeAgentMessage: (request) => this.acknowledgeAgentMessage(request),
486
+ closeAgentChannel: (request) => this.closeAgentChannel(request),
455
487
  createBundle: (request) => this.createCommunicationBundle(request),
456
488
  getBundle: (bundleId) => this.getCommunicationBundle(bundleId),
457
489
  listBundles: (request) => this.listCommunicationBundles(request),
@@ -489,6 +521,7 @@ export class AIEngineClient {
489
521
  stopCoordinationPingPong: (request) => this.stopCoordinationPingPong(request),
490
522
  checkCoordinationPingPongPreflight: (request) => this.checkCoordinationPingPongPreflight(request),
491
523
  connectToTransferChannel: (request) => this.connectToTransferChannel(request),
524
+ startAgentConnection: (request) => this.startAgentConnection(request),
492
525
  respondToMessageWatch: (request) => this.respondToMessageWatch(request),
493
526
  };
494
527
  this.collaboration = {
@@ -499,6 +532,13 @@ export class AIEngineClient {
499
532
  raiseBlocker: (request) => this.raiseCollaborationBlocker(request),
500
533
  beginImplementation: (request) => this.beginCollaborationImplementation(request),
501
534
  requestClosure: (request) => this.requestCollaborationClosure(request),
535
+ openAgentChannel: (request) => this.openAgentChannel(request),
536
+ startAgentConnection: (request) => this.startAgentConnection(request),
537
+ acceptAgentChannel: (request) => this.acceptAgentChannel(request),
538
+ postAgentHeartbeat: (request) => this.postAgentHeartbeat(request),
539
+ postAgentMessage: (request) => this.postAgentMessage(request),
540
+ acknowledgeAgentMessage: (request) => this.acknowledgeAgentMessage(request),
541
+ closeAgentChannel: (request) => this.closeAgentChannel(request),
502
542
  whoIsOnline: (request) => this.whoIsOnline(request),
503
543
  findOnlineParticipant: (request) => this.findOnlineParticipant(request),
504
544
  listCommunicationChannels: (request) => this.listCommunicationChannels(request),
@@ -533,6 +573,9 @@ export class AIEngineClient {
533
573
  apiKey: options.apiKey || process.env.AI_ENGINE_API_KEY || null,
534
574
  clientId: options.clientId || process.env.AI_ENGINE_CLIENT_ID || null,
535
575
  actorId: options.actorId || process.env.AI_ENGINE_ACTOR_ID || 'sdk:npm-ai-engine-client',
576
+ agentSessionId: options.agentSessionId || process.env.GOVERNANCE_SESSION_ID || process.env.AI_ENGINE_SESSION_ID || null,
577
+ fetchImpl: options.fetchImpl || null,
578
+ timeoutMs: options.timeoutMs,
536
579
  });
537
580
  }
538
581
 
@@ -1022,7 +1065,7 @@ export class AIEngineClient {
1022
1065
  participant_role: cleanText(participant_role) || cleanText(participantRole),
1023
1066
  current_phase: cleanText(current_phase) || cleanText(currentPhase),
1024
1067
  current_task_summary: cleanText(current_task_summary) || cleanText(currentTaskSummary),
1025
- agent_session_id: cleanText(agent_session_id) || cleanText(agentSessionId),
1068
+ agent_session_id: cleanText(agent_session_id) || cleanText(agentSessionId) || this.agentSessionId,
1026
1069
  actor_session_id: cleanText(actor_session_id) || cleanText(actorSessionId),
1027
1070
  observed_at: cleanText(observed_at) || cleanText(observedAt),
1028
1071
  metadata: isPlainObject(metadata) ? metadata : {},
@@ -1068,7 +1111,7 @@ export class AIEngineClient {
1068
1111
  participant_role: cleanText(participant_role) || cleanText(participantRole),
1069
1112
  current_phase: cleanText(current_phase) || cleanText(currentPhase),
1070
1113
  current_task_summary: cleanText(current_task_summary) || cleanText(currentTaskSummary),
1071
- agent_session_id: cleanText(agent_session_id) || cleanText(agentSessionId),
1114
+ agent_session_id: cleanText(agent_session_id) || cleanText(agentSessionId) || this.agentSessionId,
1072
1115
  actor_session_id: cleanText(actor_session_id) || cleanText(actorSessionId),
1073
1116
  observed_at: cleanText(observed_at) || cleanText(observedAt),
1074
1117
  metadata: isPlainObject(metadata) ? metadata : {},
@@ -1179,10 +1222,20 @@ export class AIEngineClient {
1179
1222
  } = {}) {
1180
1223
  const normalizedTransferChannelId = cleanText(transfer_channel_id) || cleanText(transferChannelId) || cleanText(channel_id) || cleanText(channelId);
1181
1224
  if (!normalizedTransferChannelId) throw new Error('transfer_channel_id is required.');
1225
+ let normalizedPacketId = cleanText(work_transfer_packet_id) || cleanText(workTransferPacketId) || cleanText(packet_id) || cleanText(packetId);
1226
+ if (!normalizedPacketId) {
1227
+ try {
1228
+ const status = await this.getCommunicationChannelStatus({ transferChannelId: normalizedTransferChannelId });
1229
+ normalizedPacketId = cleanText(status?.packet_id || status?.packetId || status?.work_transfer_packet_id);
1230
+ } catch (error) {
1231
+ void error;
1232
+ }
1233
+ }
1234
+ if (!normalizedPacketId) throw new Error('work_transfer_packet_id is required.');
1182
1235
  return this._request(`/api/agent-communications/transfer-channels/${encodeURIComponent(normalizedTransferChannelId)}/connect`, {
1183
1236
  method: 'POST',
1184
1237
  body: {
1185
- work_transfer_packet_id: cleanText(work_transfer_packet_id) || cleanText(workTransferPacketId) || cleanText(packet_id) || cleanText(packetId) || resolved.packet_id,
1238
+ work_transfer_packet_id: normalizedPacketId,
1186
1239
  workflow_run_id: cleanText(workflow_run_id) || cleanText(workflowRunId),
1187
1240
  participant_role: cleanText(participant_role) || cleanText(participantRole),
1188
1241
  expected_peer_role: cleanText(expected_peer_role) || cleanText(expectedPeerRole),
@@ -1190,7 +1243,7 @@ export class AIEngineClient {
1190
1243
  proposal_id: cleanText(proposal_id) || cleanText(proposalId) || cleanText(collaboration_proposal_id) || cleanText(collaborationProposalId),
1191
1244
  mode: cleanText(mode) || 'communication_participant',
1192
1245
  participant_label: cleanText(participant_label) || cleanText(participantLabel) || cleanText(participant_role_key) || cleanText(participantRoleKey),
1193
- agent_session_id: cleanText(agent_session_id) || cleanText(agentSessionId),
1246
+ agent_session_id: cleanText(agent_session_id) || cleanText(agentSessionId) || this.agentSessionId,
1194
1247
  actor_session_id: cleanText(actor_session_id) || cleanText(actorSessionId),
1195
1248
  phase: cleanText(current_phase) || cleanText(currentPhase) || cleanText(phase),
1196
1249
  current_task_summary: cleanText(current_task_summary) || cleanText(currentTaskSummary),
@@ -1205,6 +1258,366 @@ export class AIEngineClient {
1205
1258
  });
1206
1259
  }
1207
1260
 
1261
+ async openAgentChannel(request = {}) {
1262
+ return this.connectToTransferChannel(request);
1263
+ }
1264
+
1265
+ async startAgentConnection({
1266
+ workflowRunId,
1267
+ workflow_run_id,
1268
+ upstreamAgent,
1269
+ upstream_agent,
1270
+ upstreamAgentSessionId,
1271
+ upstream_agent_session_id,
1272
+ upstreamAgentId,
1273
+ upstream_agent_id,
1274
+ upstreamRole,
1275
+ upstream_role,
1276
+ recipientMode,
1277
+ recipient_mode,
1278
+ purpose,
1279
+ objective,
1280
+ mode = 'handoff',
1281
+ firstMessage = {},
1282
+ first_message = {},
1283
+ expectedMessageKind,
1284
+ expected_message_kind,
1285
+ participantRole,
1286
+ participant_role,
1287
+ participantLabel,
1288
+ participant_label,
1289
+ senderAgentSessionId,
1290
+ sender_agent_session_id,
1291
+ senderActorSessionId,
1292
+ sender_actor_session_id,
1293
+ cleanupPolicy,
1294
+ cleanup_policy,
1295
+ staleAfterSeconds = 300,
1296
+ stale_after_seconds,
1297
+ operatorNudge,
1298
+ operator_nudge,
1299
+ metadata = {},
1300
+ } = {}) {
1301
+ const normalizedFirstMessage = isPlainObject(firstMessage) ? firstMessage : isPlainObject(first_message) ? first_message : {};
1302
+ const normalizedTransferKind = normalizeTransferKind(cleanText(mode) || 'handoff');
1303
+ let normalizedWorkflowRunId = cleanText(workflow_run_id) || cleanText(workflowRunId);
1304
+ if (!normalizedWorkflowRunId) {
1305
+ try {
1306
+ const status = await this.currentWorkflowStatus();
1307
+ normalizedWorkflowRunId =
1308
+ cleanText(status?.workflow_run_id)
1309
+ || cleanText(status?.workflowRunId)
1310
+ || cleanText(status?.current_workflow_run_id)
1311
+ || cleanText(status?.currentWorkflowRunId)
1312
+ || cleanText(status?.summary?.workflow_run_id)
1313
+ || cleanText(status?.summary?.workflowRunId)
1314
+ || cleanText(status?.summary?.current_workflow_run_id)
1315
+ || cleanText(status?.summary?.currentWorkflowRunId);
1316
+ } catch (error) {
1317
+ void error;
1318
+ }
1319
+ }
1320
+ if (!normalizedWorkflowRunId) {
1321
+ throw new Error('workflow_run_id is required to start an agent connection.');
1322
+ }
1323
+ const normalizedUpstreamAgent = cleanText(upstream_agent) || cleanText(upstreamAgent) || cleanText(upstream_agent_session_id) || cleanText(upstreamAgentSessionId) || cleanText(upstream_agent_id) || cleanText(upstreamAgentId);
1324
+ const normalizedRecipientMode = cleanText(recipient_mode) || cleanText(recipientMode) || (normalizedUpstreamAgent ? 'agent_session' : 'role');
1325
+ const normalizedParticipantRole = cleanText(participant_role) || cleanText(participantRole) || 'downstream';
1326
+ const normalizedParticipantLabel = cleanText(participant_label) || cleanText(participantLabel) || normalizedParticipantRole;
1327
+ const normalizedSenderAgentSessionId = cleanText(sender_agent_session_id) || cleanText(senderAgentSessionId) || this.agentSessionId;
1328
+ const normalizedSenderActorSessionId = cleanText(sender_actor_session_id) || cleanText(senderActorSessionId);
1329
+ const normalizedFirstMessageKind = normalizeConnectionFirstMessageKind(
1330
+ cleanText(normalizedFirstMessage.kind) || cleanText(normalizedFirstMessage.message_kind) || cleanText(normalizedFirstMessage.messageKind),
1331
+ normalizedTransferKind,
1332
+ );
1333
+ const normalizedExpectedMessageKind = cleanText(expected_message_kind) || cleanText(expectedMessageKind) || 'connection_accepted';
1334
+ const normalizedObjective = cleanText(objective) || cleanText(purpose) || cleanText(normalizedFirstMessage.body) || cleanText(normalizedFirstMessage.body_markdown) || cleanText(normalizedFirstMessage.bodyMarkdown) || 'Establish governed coordination.';
1335
+ const transferResult = await this.transferWorkPacket({
1336
+ workflowRunId: normalizedWorkflowRunId,
1337
+ transferKind: normalizedTransferKind,
1338
+ objective: normalizedObjective,
1339
+ requestedOutcome: cleanText(purpose) || normalizedObjective,
1340
+ target: {
1341
+ intent: normalizedTransferKind,
1342
+ recipient_mode: normalizedRecipientMode,
1343
+ preferred_agent_session_id: normalizedUpstreamAgent,
1344
+ preferred_role_key: cleanText(upstream_role) || cleanText(upstreamRole),
1345
+ },
1346
+ artifacts: [],
1347
+ issues: [],
1348
+ expectedEvidence: [],
1349
+ preferredModes: ['inline_payload', 'bundle', 'artifact_refs'],
1350
+ capabilities: {},
1351
+ senderAgentSessionId: normalizedSenderAgentSessionId,
1352
+ senderActorSessionId: normalizedSenderActorSessionId,
1353
+ subject: cleanText(purpose) || normalizedObjective,
1354
+ bodyMarkdown:
1355
+ cleanText(normalizedFirstMessage.body_markdown)
1356
+ || cleanText(normalizedFirstMessage.bodyMarkdown)
1357
+ || cleanText(normalizedFirstMessage.body)
1358
+ || `Connection request: ${normalizedObjective}`,
1359
+ cleanupPolicy: cleanText(cleanup_policy) || cleanText(cleanupPolicy),
1360
+ messageKind: normalizedFirstMessageKind,
1361
+ message_kind: normalizedFirstMessageKind,
1362
+ metadata: isPlainObject(metadata) ? metadata : {},
1363
+ });
1364
+ const transferChannel = transferResult.communication_transfer_channel || {};
1365
+ const connection = await this.connectToTransferChannel({
1366
+ transferChannelId: transferChannel.transfer_channel_id || transferChannel.channel_id || transferResult.channel_id,
1367
+ workTransferPacketId: transferResult.work_transfer_packet?.work_transfer_packet_id || transferResult.packet_id || transferResult.transfer_packet_id,
1368
+ workflowRunId: normalizedWorkflowRunId,
1369
+ participantRole: normalizedParticipantRole,
1370
+ expectedPeerRole: cleanText(upstream_role) || cleanText(upstreamRole) || 'upstream',
1371
+ expectedMessageKind: normalizedExpectedMessageKind,
1372
+ proposalId: transferResult.transfer_negotiation?.proposal_id,
1373
+ mode: 'communication_participant',
1374
+ participantLabel: normalizedParticipantLabel,
1375
+ senderAgentSessionId: normalizedSenderAgentSessionId,
1376
+ senderActorSessionId: normalizedSenderActorSessionId,
1377
+ currentPhase: 'channel_ready',
1378
+ currentTaskSummary: cleanText(purpose) || normalizedObjective,
1379
+ expectedPayload: {
1380
+ purpose: cleanText(purpose) || normalizedObjective,
1381
+ first_message_kind: normalizedFirstMessageKind,
1382
+ first_message_body:
1383
+ cleanText(normalizedFirstMessage.body_markdown)
1384
+ || cleanText(normalizedFirstMessage.bodyMarkdown)
1385
+ || cleanText(normalizedFirstMessage.body)
1386
+ || null,
1387
+ },
1388
+ lastSeenMessageId: transferResult.communication_message?.agent_message_id,
1389
+ staleAfterSeconds: stale_after_seconds ?? staleAfterSeconds,
1390
+ operatorNudge:
1391
+ cleanText(operator_nudge)
1392
+ || cleanText(operatorNudge)
1393
+ || `upstream, please send ${normalizedExpectedMessageKind}.`,
1394
+ observedAt: transferResult.communication_message?.created_at || transferResult.transfer_receipt?.created_at,
1395
+ metadata: {
1396
+ ...(isPlainObject(metadata) ? metadata : {}),
1397
+ start_agent_connection: true,
1398
+ },
1399
+ });
1400
+ const handshake = connection.handshake || {};
1401
+ const status = connection.connected ? 'waiting' : (connection.stop_reason ? 'failed' : 'waiting');
1402
+ const transferPacketId = transferResult.work_transfer_packet?.work_transfer_packet_id || transferResult.transfer_receipt?.transfer_packet_id || transferResult.packet_id || null;
1403
+ const channelId = connection.channel_id || transferChannel.transfer_channel_id || transferChannel.channel_id || null;
1404
+ return {
1405
+ status,
1406
+ channel_id: channelId,
1407
+ transfer_packet_id: transferPacketId,
1408
+ correlation_id: connection.correlation_id || handshake.correlation_id || null,
1409
+ handshake_state: connection.handshake_state || handshake.handshake_state || null,
1410
+ waiting_side: connection.waiting_on || connection.expected_from || handshake.waiting_side || null,
1411
+ expected_message: connection.expected_message_kind || handshake.expected_message_kind || normalizedExpectedMessageKind,
1412
+ last_heartbeat_at: handshake.last_heartbeat_at || connection.collaboration_heartbeat?.observed_at || null,
1413
+ last_receipt_id: handshake.last_receipt_id || transferResult.transfer_receipt?.receipt_id || null,
1414
+ operator_nudge: connection.operator_nudge || handshake.operator_nudge || null,
1415
+ handshake,
1416
+ connection,
1417
+ transfer: transferResult,
1418
+ first_message: {
1419
+ kind: normalizedFirstMessageKind,
1420
+ body: cleanText(normalizedFirstMessage.body_markdown) || cleanText(normalizedFirstMessage.bodyMarkdown) || cleanText(normalizedFirstMessage.body) || null,
1421
+ },
1422
+ transfer_channel: transferChannel,
1423
+ transfer_receipt: transferResult.transfer_receipt || null,
1424
+ communication_message: transferResult.communication_message || null,
1425
+ };
1426
+ }
1427
+
1428
+ async _resolveMessageWatchId(request = {}) {
1429
+ const directWatchId = cleanText(request.message_watch_id) || cleanText(request.messageWatchId) || cleanText(request.watch_id) || cleanText(request.watchId);
1430
+ if (directWatchId) {
1431
+ return directWatchId;
1432
+ }
1433
+ const normalizedTransferChannelId = cleanText(request.transfer_channel_id) || cleanText(request.transferChannelId) || cleanText(request.channel_id) || cleanText(request.channelId);
1434
+ if (!normalizedTransferChannelId) return null;
1435
+ try {
1436
+ const watches = await this._request(`/api/agent-communications/transfer-channels/${encodeURIComponent(normalizedTransferChannelId)}/message-watches`);
1437
+ const watchRows = Array.isArray(watches?.message_watches) ? watches.message_watches.filter((row) => row && typeof row === 'object') : [];
1438
+ watchRows.sort((a, b) => String(b.updated_at || b.created_at || '').localeCompare(String(a.updated_at || a.created_at || '')));
1439
+ const activeWatch = watchRows.find((watch) => ['watching', 'waiting', 'stale', 'blocked', 'active'].includes(String(watch.current_status || '').trim().toLowerCase()));
1440
+ return cleanText((activeWatch || watchRows[0] || {}).message_watch_id);
1441
+ } catch (error) {
1442
+ void error;
1443
+ return null;
1444
+ }
1445
+ }
1446
+
1447
+ async acceptAgentChannel({
1448
+ messageWatchId,
1449
+ message_watch_id,
1450
+ watchId,
1451
+ watch_id,
1452
+ observedMessageId,
1453
+ observed_message_id,
1454
+ observedMessageKind,
1455
+ observed_message_kind,
1456
+ expectedMessageKind,
1457
+ expected_message_kind,
1458
+ transferChannelId,
1459
+ transfer_channel_id,
1460
+ channelId,
1461
+ channel_id,
1462
+ lastCheckedAt,
1463
+ last_checked_at,
1464
+ operatorNudge,
1465
+ operator_nudge,
1466
+ metadata = {},
1467
+ } = {}) {
1468
+ const normalizedWatchId = cleanText(message_watch_id) || cleanText(messageWatchId) || cleanText(watch_id) || cleanText(watchId) || await this._resolveMessageWatchId({ transfer_channel_id, transferChannelId, channel_id, channelId });
1469
+ if (!normalizedWatchId) throw new Error('message_watch_id is required.');
1470
+ return this._request(`/api/agent-communications/message-watches/${encodeURIComponent(normalizedWatchId)}/acknowledge`, {
1471
+ method: 'POST',
1472
+ body: {
1473
+ observed_message_id: cleanText(observed_message_id) || cleanText(observedMessageId),
1474
+ observed_message_kind: cleanText(observed_message_kind) || cleanText(observedMessageKind) || cleanText(expected_message_kind) || cleanText(expectedMessageKind),
1475
+ last_checked_at: last_checked_at || lastCheckedAt,
1476
+ operator_nudge: cleanText(operator_nudge) || cleanText(operatorNudge),
1477
+ metadata: isPlainObject(metadata) ? metadata : {},
1478
+ },
1479
+ });
1480
+ }
1481
+
1482
+ async postAgentHeartbeat({
1483
+ transferChannelId,
1484
+ transfer_channel_id,
1485
+ channelId,
1486
+ channel_id,
1487
+ workTransferPacketId,
1488
+ work_transfer_packet_id,
1489
+ packetId,
1490
+ packet_id,
1491
+ workflowRunId,
1492
+ workflow_run_id,
1493
+ participantRole,
1494
+ participant_role,
1495
+ role,
1496
+ activityState,
1497
+ activity_state,
1498
+ agentSessionId,
1499
+ agent_session_id,
1500
+ actorSessionId,
1501
+ actor_session_id,
1502
+ currentPhase,
1503
+ current_phase,
1504
+ phase,
1505
+ currentTaskSummary,
1506
+ current_task_summary,
1507
+ isActive,
1508
+ is_active,
1509
+ observedAt,
1510
+ observed_at,
1511
+ metadata = {},
1512
+ } = {}) {
1513
+ const normalizedTransferChannelId = cleanText(transfer_channel_id) || cleanText(transferChannelId) || cleanText(channel_id) || cleanText(channelId);
1514
+ if (!normalizedTransferChannelId) throw new Error('transfer_channel_id is required.');
1515
+ let normalizedPacketId = cleanText(work_transfer_packet_id) || cleanText(workTransferPacketId) || cleanText(packet_id) || cleanText(packetId);
1516
+ if (!normalizedPacketId) {
1517
+ try {
1518
+ const status = await this.getCommunicationChannelStatus({ transferChannelId: normalizedTransferChannelId });
1519
+ normalizedPacketId = cleanText(status?.packet_id || status?.packetId || status?.work_transfer_packet_id);
1520
+ } catch (error) {
1521
+ void error;
1522
+ }
1523
+ }
1524
+ if (!normalizedPacketId) throw new Error('work_transfer_packet_id is required.');
1525
+ return this._request(`/api/agent-communications/transfer-channels/${encodeURIComponent(normalizedTransferChannelId)}/heartbeats`, {
1526
+ method: 'POST',
1527
+ body: {
1528
+ work_transfer_packet_id: normalizedPacketId,
1529
+ workflow_run_id: cleanText(workflow_run_id) || cleanText(workflowRunId),
1530
+ participant_role: cleanText(participant_role) || cleanText(participantRole) || cleanText(role),
1531
+ activity_state: cleanText(activity_state) || cleanText(activityState) || 'active',
1532
+ agent_session_id: cleanText(agent_session_id) || cleanText(agentSessionId) || this.agentSessionId,
1533
+ actor_session_id: cleanText(actor_session_id) || cleanText(actorSessionId),
1534
+ current_phase: cleanText(current_phase) || cleanText(currentPhase) || cleanText(phase),
1535
+ current_task_summary: cleanText(current_task_summary) || cleanText(currentTaskSummary),
1536
+ is_active: is_active ?? isActive ?? true,
1537
+ observed_at: observed_at || observedAt,
1538
+ metadata: isPlainObject(metadata) ? metadata : {},
1539
+ },
1540
+ });
1541
+ }
1542
+
1543
+ async postAgentMessage(request = {}) {
1544
+ return this._sendAgentCommsMessage(request);
1545
+ }
1546
+
1547
+ async acknowledgeAgentMessage({
1548
+ transferChannelId,
1549
+ transfer_channel_id,
1550
+ channelId,
1551
+ channel_id,
1552
+ messageWatchId,
1553
+ message_watch_id,
1554
+ watchId,
1555
+ watch_id,
1556
+ messageId,
1557
+ message_id,
1558
+ messageKind,
1559
+ message_kind,
1560
+ observedMessageId,
1561
+ observed_message_id,
1562
+ observedMessageKind,
1563
+ observed_message_kind,
1564
+ operatorNudge,
1565
+ operator_nudge,
1566
+ metadata = {},
1567
+ } = {}) {
1568
+ const normalizedWatchId = cleanText(message_watch_id) || cleanText(messageWatchId) || cleanText(watch_id) || cleanText(watchId) || await this._resolveMessageWatchId({ transfer_channel_id, transferChannelId, channel_id, channelId });
1569
+ if (!normalizedWatchId) throw new Error('message_watch_id is required.');
1570
+ return this._request(`/api/agent-communications/message-watches/${encodeURIComponent(normalizedWatchId)}/acknowledge-message`, {
1571
+ method: 'POST',
1572
+ body: {
1573
+ observed_message_id: cleanText(observed_message_id) || cleanText(observedMessageId) || cleanText(message_id) || cleanText(messageId),
1574
+ observed_message_kind: cleanText(observed_message_kind) || cleanText(observedMessageKind) || cleanText(message_kind) || cleanText(messageKind),
1575
+ operator_nudge: cleanText(operator_nudge) || cleanText(operatorNudge),
1576
+ metadata: isPlainObject(metadata) ? metadata : {},
1577
+ },
1578
+ });
1579
+ }
1580
+
1581
+ async closeAgentChannel({
1582
+ transferChannelId,
1583
+ transfer_channel_id,
1584
+ channelId,
1585
+ channel_id,
1586
+ closureStatus,
1587
+ closure_status,
1588
+ closureReason,
1589
+ closure_reason,
1590
+ failureReason,
1591
+ failure_reason,
1592
+ evidence = {},
1593
+ evidenceManifestSha256,
1594
+ evidence_manifest_sha256,
1595
+ closedByAgentSessionId,
1596
+ closed_by_agent_session_id,
1597
+ closedByActorSessionId,
1598
+ closed_by_actor_session_id,
1599
+ closedByClaimId,
1600
+ closed_by_claim_id,
1601
+ metadata = {},
1602
+ } = {}) {
1603
+ const normalizedTransferChannelId = cleanText(transfer_channel_id) || cleanText(transferChannelId) || cleanText(channel_id) || cleanText(channelId);
1604
+ if (!normalizedTransferChannelId) throw new Error('transfer_channel_id is required.');
1605
+ return this._request(`/api/agent-communications/transfer-channels/${encodeURIComponent(normalizedTransferChannelId)}/close`, {
1606
+ method: 'POST',
1607
+ body: {
1608
+ closure_status: cleanText(closure_status) || cleanText(closureStatus) || 'closed',
1609
+ closure_reason: cleanText(closure_reason) || cleanText(closureReason),
1610
+ failure_reason: cleanText(failure_reason) || cleanText(failureReason),
1611
+ evidence: isPlainObject(evidence) ? evidence : {},
1612
+ evidence_manifest_sha256: cleanText(evidence_manifest_sha256) || cleanText(evidenceManifestSha256),
1613
+ closed_by_agent_session_id: cleanText(closed_by_agent_session_id) || cleanText(closedByAgentSessionId),
1614
+ closed_by_actor_session_id: cleanText(closed_by_actor_session_id) || cleanText(closedByActorSessionId),
1615
+ closed_by_claim_id: cleanText(closed_by_claim_id) || cleanText(closedByClaimId),
1616
+ metadata: isPlainObject(metadata) ? metadata : {},
1617
+ },
1618
+ });
1619
+ }
1620
+
1208
1621
  async respondToMessageWatch({
1209
1622
  transferChannelId,
1210
1623
  transfer_channel_id,
@@ -1241,7 +1654,7 @@ export class AIEngineClient {
1241
1654
  message_watch_id: cleanText(message_watch_id) || cleanText(messageWatchId) || cleanText(watch_id) || cleanText(watchId),
1242
1655
  expected_message_kind: cleanText(expected_message_kind) || cleanText(expectedMessageKind),
1243
1656
  sender_role: cleanText(sender_role) || cleanText(senderRole) || cleanText(participant_role) || cleanText(participantRole),
1244
- sender_agent_session_id: cleanText(sender_agent_session_id) || cleanText(senderAgentSessionId),
1657
+ sender_agent_session_id: cleanText(sender_agent_session_id) || cleanText(senderAgentSessionId) || this.agentSessionId,
1245
1658
  sender_actor_session_id: cleanText(sender_actor_session_id) || cleanText(senderActorSessionId),
1246
1659
  message_kind: cleanText(message_kind) || cleanText(messageKind),
1247
1660
  body_markdown: cleanText(body_markdown) || cleanText(bodyMarkdown),
@@ -1417,7 +1830,7 @@ export class AIEngineClient {
1417
1830
  return this._request(`/api/agent-communications/transfer-channels/${encodeURIComponent(normalizedTransferChannelId)}/collaboration/request-closure`, {
1418
1831
  method: 'POST',
1419
1832
  body: {
1420
- sender_agent_session_id: cleanText(sender_agent_session_id) || cleanText(senderAgentSessionId),
1833
+ sender_agent_session_id: cleanText(sender_agent_session_id) || cleanText(senderAgentSessionId) || this.agentSessionId,
1421
1834
  sender_actor_session_id: cleanText(sender_actor_session_id) || cleanText(senderActorSessionId),
1422
1835
  closure_reason: cleanText(closure_reason) || cleanText(closureReason),
1423
1836
  evidence_refs: Array.isArray(evidence_refs) ? evidence_refs : evidenceRefs,
@@ -1612,6 +2025,8 @@ export class AIEngineClient {
1612
2025
  sender_agent_session_id,
1613
2026
  senderActorSessionId,
1614
2027
  sender_actor_session_id,
2028
+ messageKind,
2029
+ message_kind,
1615
2030
  subject,
1616
2031
  bodyMarkdown,
1617
2032
  body_markdown,
@@ -1654,8 +2069,9 @@ export class AIEngineClient {
1654
2069
  estimated_payload_kb: Number(estimated_payload_kb ?? estimatedPayloadKb ?? 0) || undefined,
1655
2070
  requires_receipts: Boolean(requires_receipts ?? requiresReceipts),
1656
2071
  supports_hash_validation: Boolean(supports_hash_validation ?? supportsHashValidation),
1657
- sender_agent_session_id: cleanText(sender_agent_session_id) || cleanText(senderAgentSessionId),
2072
+ sender_agent_session_id: cleanText(sender_agent_session_id) || cleanText(senderAgentSessionId) || this.agentSessionId,
1658
2073
  sender_actor_session_id: cleanText(sender_actor_session_id) || cleanText(senderActorSessionId),
2074
+ message_kind: cleanText(message_kind) || cleanText(messageKind),
1659
2075
  subject: cleanText(subject),
1660
2076
  body_markdown: cleanText(body_markdown) || cleanText(bodyMarkdown),
1661
2077
  parent_thread_id: cleanText(parent_thread_id) || cleanText(parentThreadId),
@@ -1826,7 +2242,7 @@ export class AIEngineClient {
1826
2242
  transfer_channel_id: normalizedTransferChannelId,
1827
2243
  workflow_run_id: cleanText(workflow_run_id) || cleanText(workflowRunId),
1828
2244
  body_markdown: cleanText(body_markdown) || cleanText(bodyMarkdown),
1829
- sender_agent_session_id: cleanText(sender_agent_session_id) || cleanText(senderAgentSessionId),
2245
+ sender_agent_session_id: cleanText(sender_agent_session_id) || cleanText(senderAgentSessionId) || this.agentSessionId,
1830
2246
  sender_role: cleanText(sender_role) || cleanText(senderRole),
1831
2247
  recipient_agent_session_id: cleanText(recipient_agent_session_id) || cleanText(recipientAgentSessionId),
1832
2248
  recipient_role: cleanText(recipient_role) || cleanText(recipientRole) || cleanText(role),
@@ -1878,7 +2294,7 @@ export class AIEngineClient {
1878
2294
  transfer_channel_id: normalizedTransferChannelId,
1879
2295
  workflow_run_id: cleanText(workflow_run_id) || cleanText(workflowRunId),
1880
2296
  body_markdown: cleanText(body_markdown) || cleanText(bodyMarkdown),
1881
- sender_agent_session_id: cleanText(sender_agent_session_id) || cleanText(senderAgentSessionId),
2297
+ sender_agent_session_id: cleanText(sender_agent_session_id) || cleanText(senderAgentSessionId) || this.agentSessionId,
1882
2298
  sender_role: cleanText(sender_role) || cleanText(senderRole),
1883
2299
  recipient_agent_session_id: cleanText(recipient_agent_session_id) || cleanText(recipientAgentSessionId),
1884
2300
  recipient_role: cleanText(recipient_role) || cleanText(recipientRole) || cleanText(role) || cleanText(participant_role) || cleanText(participantRole),
@@ -2305,7 +2721,7 @@ export class AIEngineClient {
2305
2721
  body: {
2306
2722
  communication_thread_id: cleanText(communication_thread_id) || cleanText(communicationThreadId) || cleanText(threadId),
2307
2723
  communication_bundle_id: cleanText(communication_bundle_id) || cleanText(communicationBundleId),
2308
- sender_agent_session_id: cleanText(sender_agent_session_id) || cleanText(senderAgentSessionId),
2724
+ sender_agent_session_id: cleanText(sender_agent_session_id) || cleanText(senderAgentSessionId) || this.agentSessionId,
2309
2725
  recipient_agent_session_id: cleanText(recipient_agent_session_id) || cleanText(recipientAgentSessionId),
2310
2726
  recipient_role_key: cleanText(recipient_role_key) || cleanText(recipientRoleKey),
2311
2727
  message_kind: normalizeMessageKind(cleanText(message_kind) || cleanText(messageKind)),
@@ -2595,7 +3011,7 @@ export class AIEngineClient {
2595
3011
  receipt_type: normalizeTransferReceiptType(cleanText(receipt_type) || cleanText(receiptType) || 'delivery_receipt'),
2596
3012
  receipt_status: cleanText(receipt_status) || cleanText(receiptStatus) || 'recorded',
2597
3013
  actor_session_id: cleanText(actor_session_id) || cleanText(actorSessionId),
2598
- agent_session_id: cleanText(agent_session_id) || cleanText(agentSessionId),
3014
+ agent_session_id: cleanText(agent_session_id) || cleanText(agentSessionId) || this.agentSessionId,
2599
3015
  claim_id: cleanText(claim_id) || cleanText(claimId),
2600
3016
  evidence_ref: cleanText(evidence_ref) || cleanText(evidenceRef),
2601
3017
  evidence_sha256: cleanText(evidence_sha256) || cleanText(evidenceSha256),
@@ -2777,7 +3193,7 @@ export class AIEngineClient {
2777
3193
  body: {
2778
3194
  workflow_run_id: cleanText(workflow_run_id) || cleanText(workflowRunId),
2779
3195
  title: cleanText(title),
2780
- agent_session_id: cleanText(agent_session_id) || cleanText(agentSessionId),
3196
+ agent_session_id: cleanText(agent_session_id) || cleanText(agentSessionId) || this.agentSessionId,
2781
3197
  handoff_kind: cleanText(handoff_kind) || cleanText(handoffKind) || 'general',
2782
3198
  handoff_priority: cleanText(handoff_priority) || cleanText(handoffPriority) || 'normal',
2783
3199
  summary_text: cleanText(summary_text) || cleanText(summaryText),
@@ -5386,6 +5802,7 @@ export class AIEngineClient {
5386
5802
  const resolvedHeaders = {
5387
5803
  accept: accept || 'application/json',
5388
5804
  'x-actor-id': this.actorId,
5805
+ ...(this.agentSessionId ? { 'x-agent-session-id': this.agentSessionId } : {}),
5389
5806
  'x-ai-engine-client-version': this.clientVersion,
5390
5807
  'x-ai-engine-client-capabilities': this.clientCapabilities.join(','),
5391
5808
  ...(isJsonBody(body) ? { 'content-type': 'application/json' } : {}),