@openscout/scout 0.2.75 → 0.2.76

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28706,6 +28706,9 @@ function isLocalAgentRecordOnline(agentName, record) {
28706
28706
  }
28707
28707
  return isLocalAgentSessionAlive(normalizedRecord.tmuxSession);
28708
28708
  }
28709
+ function localAgentOnlineFlightKey(agentName, record) {
28710
+ return [agentName, record.transport, record.tmuxSession].join("\x00");
28711
+ }
28709
28712
  function isLocalAgentSessionAlive(sessionName) {
28710
28713
  return readTmuxSessionExistsSnapshot(sessionName);
28711
28714
  }
@@ -29478,6 +29481,23 @@ function areHarnessBinariesAvailable(record) {
29478
29481
  return true;
29479
29482
  }
29480
29483
  async function ensureLocalAgentOnline(agentName, record) {
29484
+ const normalizedRecord = normalizeLocalAgentRecord(agentName, record);
29485
+ const flightKey = localAgentOnlineFlightKey(agentName, normalizedRecord);
29486
+ const existingFlight = localAgentOnlineFlights.get(flightKey);
29487
+ if (existingFlight) {
29488
+ return await existingFlight;
29489
+ }
29490
+ const flight = ensureLocalAgentOnlineOnce(agentName, normalizedRecord);
29491
+ localAgentOnlineFlights.set(flightKey, flight);
29492
+ try {
29493
+ return await flight;
29494
+ } finally {
29495
+ if (localAgentOnlineFlights.get(flightKey) === flight) {
29496
+ localAgentOnlineFlights.delete(flightKey);
29497
+ }
29498
+ }
29499
+ }
29500
+ async function ensureLocalAgentOnlineOnce(agentName, record) {
29481
29501
  const normalizedRecord = normalizeLocalAgentRecord(agentName, record);
29482
29502
  if (isLocalAgentRecordOnline(agentName, normalizedRecord)) {
29483
29503
  return normalizedRecord;
@@ -30545,7 +30565,7 @@ function shouldDisableGeneratedCodexEndpoint(endpoint) {
30545
30565
  }
30546
30566
  return endpoint.metadata?.source === "scout-app";
30547
30567
  }
30548
- var MODULE_DIRECTORY, OPENSCOUT_REPO_ROOT, DEFAULT_LOCAL_AGENT_CAPABILITIES, DEFAULT_LOCAL_AGENT_HARNESS = "claude", DEFAULT_ONE_TIME_LOCAL_AGENT_CARD_TTL_MS, SUPPORTED_LOCAL_AGENT_HARNESSES, SUPPORTED_SCOUT_HARNESSES, DEFAULT_CLAUDE_SCOUT_ALLOWED_TOOLS, INVOCATION_TASK_PREVIEW_MAX_LENGTH = 96, SCOUT_MESSAGE_ATTACHMENTS_CONTEXT_KEY = "scoutMessageAttachments", TMUX_PASTE_DRAIN_MS = 150, TMUX_VERIFY_FIRST_SAMPLE_MS = 250, TMUX_VERIFY_SECOND_SAMPLE_MS = 750, TMUX_VERIFY_RETRY_SAMPLE_MS = 400, TMUX_CAPTURE_TAIL_LINES = 20, TMUX_DEFAULT_COLUMNS, TMUX_DEFAULT_ROWS, TMUX_READY_TIMEOUT_MS = 20000, TMUX_READY_POLL_MS = 250, TMUX_READY_TAIL_LINES = 80;
30568
+ var MODULE_DIRECTORY, OPENSCOUT_REPO_ROOT, DEFAULT_LOCAL_AGENT_CAPABILITIES, DEFAULT_LOCAL_AGENT_HARNESS = "claude", DEFAULT_ONE_TIME_LOCAL_AGENT_CARD_TTL_MS, SUPPORTED_LOCAL_AGENT_HARNESSES, SUPPORTED_SCOUT_HARNESSES, DEFAULT_CLAUDE_SCOUT_ALLOWED_TOOLS, localAgentOnlineFlights, INVOCATION_TASK_PREVIEW_MAX_LENGTH = 96, SCOUT_MESSAGE_ATTACHMENTS_CONTEXT_KEY = "scoutMessageAttachments", TMUX_PASTE_DRAIN_MS = 150, TMUX_VERIFY_FIRST_SAMPLE_MS = 250, TMUX_VERIFY_SECOND_SAMPLE_MS = 750, TMUX_VERIFY_RETRY_SAMPLE_MS = 400, TMUX_CAPTURE_TAIL_LINES = 20, TMUX_DEFAULT_COLUMNS, TMUX_DEFAULT_ROWS, TMUX_READY_TIMEOUT_MS = 20000, TMUX_READY_POLL_MS = 250, TMUX_READY_TAIL_LINES = 80;
30549
30569
  var init_local_agents = __esm(() => {
30550
30570
  init_codex_executable();
30551
30571
  init_src();
@@ -30592,6 +30612,7 @@ var init_local_agents = __esm(() => {
30592
30612
  "mcp__scout__work_update",
30593
30613
  "Bash(scout:*)"
30594
30614
  ];
30615
+ localAgentOnlineFlights = new Map;
30595
30616
  TMUX_DEFAULT_COLUMNS = parsePositiveInteger2(process.env.OPENSCOUT_LOCAL_AGENT_TMUX_COLUMNS, 160);
30596
30617
  TMUX_DEFAULT_ROWS = parsePositiveInteger2(process.env.OPENSCOUT_LOCAL_AGENT_TMUX_ROWS, 48);
30597
30618
  });
@@ -45460,8 +45481,16 @@ async function sendScoutConversationMessage(input) {
45460
45481
  const createdAtMs = input.createdAtMs ?? Date.now();
45461
45482
  const senderId = await resolveConversationActorId(broker2.baseUrl, broker2.snapshot, broker2.node.id, input.senderId, currentDirectory);
45462
45483
  const mentionResolution = await resolveMentionTargets(broker2.snapshot, input.body, currentDirectory);
45463
- const availableTargets = (await Promise.all(mentionResolution.resolved.map(async (target) => await ensureTargetRelayAgentRegistered(broker2.baseUrl, broker2.snapshot, broker2.node.id, target.agentId, currentDirectory) ? target : null))).filter((target) => Boolean(target));
45464
- const validTargets = [...new Set(availableTargets.map((target) => target.agentId).filter((target) => target !== senderId && Boolean(broker2.snapshot.agents[target])))].sort();
45484
+ const mentionedTargetIds = new Set(mentionResolution.resolved.map((target) => target.agentId));
45485
+ const participantTargetIds = input.notifyParticipantAgents && (conversation.kind === "channel" || conversation.kind === "group_direct" || conversation.kind === "thread") ? conversation.participantIds.filter((participantId) => isSteerableParticipant(broker2.snapshot, participantId, senderId)) : [];
45486
+ const candidateTargetIds = [...new Set([
45487
+ ...mentionedTargetIds,
45488
+ ...participantTargetIds
45489
+ ])];
45490
+ const availableTargets = (await Promise.all(candidateTargetIds.map(async (agentId) => await ensureTargetRelayAgentRegistered(broker2.baseUrl, broker2.snapshot, broker2.node.id, agentId, currentDirectory) ? agentId : null))).filter((agentId) => Boolean(agentId));
45491
+ const validTargets = [...new Set(availableTargets.filter((target) => target !== senderId && Boolean(broker2.snapshot.agents[target])))].sort();
45492
+ const mentionedValidTargets = validTargets.filter((targetId) => mentionedTargetIds.has(targetId));
45493
+ const participantValidTargets = validTargets.filter((targetId) => participantTargetIds.includes(targetId));
45465
45494
  const unresolvedTargets = mentionResolution.resolved.filter((target) => !validTargets.includes(target.agentId)).map((target) => target.label).concat(mentionResolution.unresolved).concat(mentionResolution.ambiguous.map((entry) => entry.label));
45466
45495
  const messageId = `m-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
45467
45496
  const returnAddress = buildScoutReturnAddress2(broker2.snapshot, senderId, {
@@ -45476,9 +45505,9 @@ async function sendScoutConversationMessage(input) {
45476
45505
  class: conversation.kind === "system" ? "system" : "agent",
45477
45506
  body: input.body,
45478
45507
  ...input.replyToMessageId?.trim() ? { replyToMessageId: input.replyToMessageId.trim() } : {},
45479
- mentions: mentionResolution.resolved.filter((target) => validTargets.includes(target.agentId)).map((target) => ({ actorId: target.agentId, label: target.label })),
45508
+ mentions: mentionResolution.resolved.filter((target) => mentionedValidTargets.includes(target.agentId)).map((target) => ({ actorId: target.agentId, label: target.label })),
45480
45509
  attachments: normalizeOutgoingAttachments(input.attachments),
45481
- audience: validTargets.length > 0 ? { notify: validTargets, reason: "mention" } : undefined,
45510
+ audience: participantValidTargets.length > 0 ? { notify: participantValidTargets, reason: "conversation_visibility" } : mentionedValidTargets.length > 0 ? { notify: mentionedValidTargets, reason: "mention" } : undefined,
45482
45511
  visibility: conversation.visibility,
45483
45512
  policy: "durable",
45484
45513
  createdAt: createdAtMs,
@@ -45487,11 +45516,22 @@ async function sendScoutConversationMessage(input) {
45487
45516
  destinationKind: "conversation",
45488
45517
  destinationId: conversation.id,
45489
45518
  relayMessageId: messageId,
45519
+ ...participantValidTargets.length ? {
45520
+ deliveryIntent: "group_message",
45521
+ relayTargetIds: participantValidTargets
45522
+ } : {},
45490
45523
  ...clientMessageMetadata(input.clientMessageId),
45491
45524
  returnAddress
45492
45525
  }
45493
45526
  });
45494
- return { usedBroker: true, conversationId: conversation.id, messageId, invokedTargets: validTargets, unresolvedTargets };
45527
+ return {
45528
+ usedBroker: true,
45529
+ conversationId: conversation.id,
45530
+ messageId,
45531
+ invokedTargets: mentionedValidTargets,
45532
+ ...participantValidTargets.length ? { notifiedTargets: participantValidTargets } : {},
45533
+ unresolvedTargets
45534
+ };
45495
45535
  }
45496
45536
  async function sendScoutConversationSteer(input) {
45497
45537
  const broker2 = await loadScoutBrokerContext();
@@ -62934,6 +62974,26 @@ function defaultSendModeForConversationSession(input) {
62934
62974
  }
62935
62975
  return input.hasActiveRun ? "steer" : "invoke";
62936
62976
  }
62977
+ function resolveChatMessagePlacement(chatId, replyToMessageId) {
62978
+ const conversation = queryConversationDefinitionById(chatId);
62979
+ if (conversation?.parentConversationId && conversation.messageId) {
62980
+ return {
62981
+ kind: "thread_reply",
62982
+ parentConversationId: conversation.parentConversationId,
62983
+ anchorMessageId: conversation.messageId,
62984
+ ...replyToMessageId ? { replyToMessageId } : {}
62985
+ };
62986
+ }
62987
+ return replyToMessageId ? { kind: "inline_reply", replyToMessageId } : { kind: "root" };
62988
+ }
62989
+ function semanticSessionForChat(chatId, session3) {
62990
+ if (session3.kind !== "thread")
62991
+ return session3;
62992
+ const definition = queryConversationDefinitionById(chatId);
62993
+ if (!definition?.parentConversationId)
62994
+ return session3;
62995
+ return querySessionById(definition.parentConversationId) ?? session3;
62996
+ }
62937
62997
  function steerContextByTargetAgentId(runs) {
62938
62998
  const entries2 = new Map;
62939
62999
  for (const run of runs) {
@@ -66027,6 +66087,117 @@ async function createOpenScoutWebServer(options) {
66027
66087
  }
66028
66088
  return new Response(Bun.file(entry.path), { headers });
66029
66089
  });
66090
+ const dispatchOperatorChatMessage = async (input) => {
66091
+ const routeSession = querySessionById(input.chatId);
66092
+ if (!routeSession) {
66093
+ return { ok: false, status: 404, error: "chat not found" };
66094
+ }
66095
+ const semanticSession = semanticSessionForChat(input.chatId, routeSession);
66096
+ const { conversationId: routedConversationId, senderId } = resolveConversationRouting(input.chatId);
66097
+ if (!routedConversationId) {
66098
+ return { ok: false, status: 404, error: "chat not found" };
66099
+ }
66100
+ const isOperatorDirectConversation = semanticSession.kind === "direct" && sessionIncludesOperatorParticipant(semanticSession);
66101
+ const isSharedChat = routeSession.kind === "channel" || routeSession.kind === "group_direct" || routeSession.kind === "thread" && !isOperatorDirectConversation;
66102
+ const scopedTargetParticipantIds = Array.isArray(input.targetParticipantIds) ? [...new Set(input.targetParticipantIds.filter((targetId) => typeof targetId === "string").map((targetId) => targetId.trim()).filter(Boolean))] : undefined;
66103
+ const requestedSendMode = input.requestedSendMode?.trim();
66104
+ const selectors = extractAgentSelectors(input.body);
66105
+ const selectorTargetAgentIds = resolveSendSelectorTargetAgentIds(selectors, routeSession.participantIds);
66106
+ const hasExplicitTarget = Boolean(scopedTargetParticipantIds?.length) || selectors.length > 0;
66107
+ const shouldInspectActiveRuns = requestedSendMode?.toLowerCase() === "steer" || !requestedSendMode && (isOperatorDirectConversation || hasExplicitTarget);
66108
+ const activeRuns = shouldInspectActiveRuns ? queryRuns({
66109
+ conversationId: routedConversationId,
66110
+ active: true,
66111
+ limit: 100
66112
+ }) : [];
66113
+ const resolvedTargetIds = new Set([
66114
+ ...scopedTargetParticipantIds ?? [],
66115
+ ...selectorTargetAgentIds
66116
+ ]);
66117
+ const matchedActiveRuns = hasExplicitTarget ? activeRuns.filter((run) => resolvedTargetIds.has(run.agentId)) : activeRuns;
66118
+ const hasActiveRun = matchedActiveRuns.length > 0;
66119
+ const steerContext = steerContextByTargetAgentId(matchedActiveRuns);
66120
+ const sendMode = (requestedSendMode || defaultSendModeForConversationSession({
66121
+ session: semanticSession,
66122
+ hasExplicitTarget,
66123
+ hasActiveRun
66124
+ })).toLowerCase();
66125
+ const shouldCommentOnly = sendMode === "comment" || sendMode === "message" || sendMode === "tell" && !isOperatorDirectConversation;
66126
+ const executionHarness = coerceAgentHarness(input.execution?.harness);
66127
+ const executionModel = optionalString2(input.execution?.model)?.trim();
66128
+ const requestedExecution = executionHarness || executionModel ? {
66129
+ ...executionHarness ? { harness: executionHarness } : {},
66130
+ ...executionModel ? { model: executionModel } : {}
66131
+ } : undefined;
66132
+ const result = shouldCommentOnly ? await sendScoutConversationMessage({
66133
+ conversationId: routedConversationId,
66134
+ senderId,
66135
+ body: input.body,
66136
+ attachments: input.attachments,
66137
+ replyToMessageId: input.replyToMessageId,
66138
+ notifyParticipantAgents: isSharedChat,
66139
+ currentDirectory,
66140
+ source: "scout-web"
66141
+ }) : await sendScoutConversationSteer({
66142
+ conversationId: routedConversationId,
66143
+ senderId,
66144
+ body: input.body,
66145
+ attachments: input.attachments,
66146
+ replyToMessageId: input.replyToMessageId,
66147
+ ...scopedTargetParticipantIds?.length ? { targetParticipantIds: scopedTargetParticipantIds } : {},
66148
+ intent: sendMode === "tell" ? "tell" : sendMode === "invoke" ? "invoke" : "steer",
66149
+ ...sendMode === "steer" && steerContext ? { steerContextByTargetAgentId: steerContext } : {},
66150
+ ...requestedExecution ? { execution: requestedExecution } : {},
66151
+ currentDirectory,
66152
+ source: "scout-web"
66153
+ });
66154
+ if (!result.usedBroker) {
66155
+ return { ok: false, status: 502, error: "broker unreachable" };
66156
+ }
66157
+ const flights = result.flights?.length ? result.flights : result.flight ? [result.flight] : [];
66158
+ return {
66159
+ ok: true,
66160
+ result: {
66161
+ ...result,
66162
+ conversationId: routedConversationId,
66163
+ chatId: routedConversationId,
66164
+ runIds: flights.map((flight) => `run:flight:${flight.id}`)
66165
+ }
66166
+ };
66167
+ };
66168
+ app.post("/api/chats/:chatId/messages", async (c) => {
66169
+ const chatId = c.req.param("chatId");
66170
+ if (!isOpaqueChannelId(chatId)) {
66171
+ return c.json({ error: "chatId must be an opaque chat id" }, 400);
66172
+ }
66173
+ const requestBody2 = await c.req.json().catch(() => ({}));
66174
+ const body = optionalString2(requestBody2.body) ?? "";
66175
+ if (requestBody2.attachments !== undefined && !Array.isArray(requestBody2.attachments)) {
66176
+ return c.json({ error: "attachments must be an array" }, 400);
66177
+ }
66178
+ const attachments = requestBody2.attachments;
66179
+ if (!body.trim() && !attachments?.length) {
66180
+ return c.json({ error: "body or attachments are required" }, 400);
66181
+ }
66182
+ const hasReplyAnchor = requestBody2.replyToMessageId !== undefined && requestBody2.replyToMessageId !== null;
66183
+ const replyToMessageId = hasReplyAnchor ? optionalString2(requestBody2.replyToMessageId)?.trim() : undefined;
66184
+ if (hasReplyAnchor && !replyToMessageId) {
66185
+ return c.json({ error: "replyToMessageId must be a non-empty string" }, 400);
66186
+ }
66187
+ const outcome = await dispatchOperatorChatMessage({
66188
+ chatId,
66189
+ body: body.trim(),
66190
+ ...attachments?.length ? { attachments } : {},
66191
+ ...replyToMessageId ? { replyToMessageId } : {}
66192
+ });
66193
+ if (!outcome.ok) {
66194
+ return c.json({ error: outcome.error }, outcome.status);
66195
+ }
66196
+ return c.json({
66197
+ ...outcome.result,
66198
+ placement: resolveChatMessagePlacement(chatId, replyToMessageId)
66199
+ });
66200
+ });
66030
66201
  app.post("/api/send", async (c) => {
66031
66202
  const { body, chatId, cId, conversationId, threadId, attachments, intent, mode, targetParticipantIds, replyToMessageId, execution } = await c.req.json();
66032
66203
  const messageBody = body?.trim() ?? "";
@@ -66042,11 +66213,22 @@ async function createOpenScoutWebServer(options) {
66042
66213
  if (routeCId && !isOpaqueChannelId(routeCId)) {
66043
66214
  return c.json({ error: "chatId must be an opaque chat id" }, 400);
66044
66215
  }
66045
- const routeSession = routeCId ? querySessionById(routeCId) : null;
66046
- if (routeCId && !routeSession) {
66047
- return c.json({ error: "chat not found" }, 404);
66216
+ if (routeCId) {
66217
+ const outcome = await dispatchOperatorChatMessage({
66218
+ chatId: routeCId,
66219
+ body: messageBody,
66220
+ attachments,
66221
+ replyToMessageId: routedReplyToMessageId,
66222
+ requestedSendMode: optionalString2(intent)?.trim() || optionalString2(mode)?.trim(),
66223
+ targetParticipantIds,
66224
+ execution
66225
+ });
66226
+ if (!outcome.ok) {
66227
+ return c.json({ error: outcome.error }, outcome.status);
66228
+ }
66229
+ return c.json(outcome.result);
66048
66230
  }
66049
- if (!routeCId && scoutbotRunner) {
66231
+ if (scoutbotRunner) {
66050
66232
  try {
66051
66233
  const result2 = await scoutbotRunner.postOperatorMessage({
66052
66234
  body: messageBody,
@@ -66063,7 +66245,7 @@ async function createOpenScoutWebServer(options) {
66063
66245
  return c.json({ error: message }, /unknown scoutbot thread/i.test(message) ? 404 : 500);
66064
66246
  }
66065
66247
  }
66066
- const { directAgentId, channel, conversationId: routedConversationId, senderId } = resolveConversationRouting(routeCId);
66248
+ const { directAgentId, channel, senderId } = resolveConversationRouting(undefined);
66067
66249
  if (directAgentId) {
66068
66250
  if (directAgentId === SCOUTBOT_AGENT_ID && scoutbotRunner) {
66069
66251
  try {
@@ -66096,70 +66278,6 @@ async function createOpenScoutWebServer(options) {
66096
66278
  runIds: result2.flight ? [`run:flight:${result2.flight.id}`] : []
66097
66279
  });
66098
66280
  }
66099
- if (routedConversationId) {
66100
- const isOperatorDirectConversation = routeSession?.kind === "direct" && sessionIncludesOperatorParticipant(routeSession);
66101
- const scopedTargetParticipantIds = Array.isArray(targetParticipantIds) ? [...new Set(targetParticipantIds.filter((targetId) => typeof targetId === "string").map((targetId) => targetId.trim()).filter(Boolean))] : undefined;
66102
- const requestedSendMode = optionalString2(intent)?.trim() || optionalString2(mode)?.trim();
66103
- const selectors = extractAgentSelectors(messageBody);
66104
- const selectorTargetAgentIds = resolveSendSelectorTargetAgentIds(selectors, routeSession?.participantIds ?? []);
66105
- const hasExplicitTarget = Boolean(scopedTargetParticipantIds?.length) || selectors.length > 0;
66106
- const shouldInspectActiveRuns = requestedSendMode?.toLowerCase() === "steer" || !requestedSendMode && (isOperatorDirectConversation || hasExplicitTarget);
66107
- const activeRuns = shouldInspectActiveRuns ? queryRuns({
66108
- conversationId: routedConversationId,
66109
- active: true,
66110
- limit: 100
66111
- }) : [];
66112
- const resolvedTargetIds = new Set([
66113
- ...scopedTargetParticipantIds ?? [],
66114
- ...selectorTargetAgentIds
66115
- ]);
66116
- const matchedActiveRuns = hasExplicitTarget ? activeRuns.filter((run) => resolvedTargetIds.has(run.agentId)) : activeRuns;
66117
- const hasActiveRun = matchedActiveRuns.length > 0;
66118
- const steerContext = steerContextByTargetAgentId(matchedActiveRuns);
66119
- const sendMode = (requestedSendMode || defaultSendModeForConversationSession({
66120
- session: routeSession,
66121
- hasExplicitTarget,
66122
- hasActiveRun
66123
- })).toLowerCase();
66124
- const shouldCommentOnly = sendMode === "comment" || sendMode === "message" || sendMode === "tell" && !isOperatorDirectConversation;
66125
- const executionHarness = coerceAgentHarness(execution?.harness);
66126
- const executionModel = optionalString2(execution?.model)?.trim();
66127
- const requestedExecution = executionHarness || executionModel ? {
66128
- ...executionHarness ? { harness: executionHarness } : {},
66129
- ...executionModel ? { model: executionModel } : {}
66130
- } : undefined;
66131
- const result2 = shouldCommentOnly ? await sendScoutConversationMessage({
66132
- conversationId: routedConversationId,
66133
- senderId,
66134
- body: messageBody,
66135
- attachments,
66136
- replyToMessageId: routedReplyToMessageId,
66137
- currentDirectory,
66138
- source: "scout-web"
66139
- }) : await sendScoutConversationSteer({
66140
- conversationId: routedConversationId,
66141
- senderId,
66142
- body: messageBody,
66143
- attachments,
66144
- replyToMessageId: routedReplyToMessageId,
66145
- ...scopedTargetParticipantIds?.length ? { targetParticipantIds: scopedTargetParticipantIds } : {},
66146
- intent: sendMode === "tell" ? "tell" : sendMode === "invoke" ? "invoke" : "steer",
66147
- ...sendMode === "steer" && steerContext ? { steerContextByTargetAgentId: steerContext } : {},
66148
- ...requestedExecution ? { execution: requestedExecution } : {},
66149
- currentDirectory,
66150
- source: "scout-web"
66151
- });
66152
- if (!result2.usedBroker) {
66153
- return c.json({ error: "broker unreachable" }, 502);
66154
- }
66155
- const flights = result2.flights?.length ? result2.flights : result2.flight ? [result2.flight] : [];
66156
- return c.json({
66157
- ...result2,
66158
- conversationId: routedConversationId,
66159
- chatId: routedConversationId,
66160
- runIds: flights.map((flight) => `run:flight:${flight.id}`)
66161
- });
66162
- }
66163
66281
  const result = await sendScoutMessage({
66164
66282
  senderId,
66165
66283
  body: messageBody,