@openscout/scout 0.2.49 → 0.2.51

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.
package/dist/main.mjs CHANGED
@@ -932,8 +932,8 @@ var init_agent_selectors = __esm(() => {
932
932
  init_agent_address();
933
933
  });
934
934
 
935
- // ../protocol/src/relay-agent-card.ts
936
- function buildRelayReturnAddress(input) {
935
+ // ../protocol/src/scout-agent-card.ts
936
+ function buildScoutReturnAddress(input) {
937
937
  const next = {
938
938
  actorId: input.actorId,
939
939
  handle: input.handle.trim()
@@ -7505,7 +7505,9 @@ var init_paths = __esm(() => {
7505
7505
  endpoints: "/v1/endpoints",
7506
7506
  conversations: "/v1/conversations",
7507
7507
  invocations: "/v1/invocations",
7508
- activity: "/v1/activity"
7508
+ activity: "/v1/activity",
7509
+ collaborationRecords: "/v1/collaboration/records",
7510
+ collaborationEvents: "/v1/collaboration/events"
7509
7511
  }
7510
7512
  };
7511
7513
  });
@@ -7610,14 +7612,14 @@ function displayNameForBrokerActor(snapshot, actorId) {
7610
7612
  function firstEndpointForActor(snapshot, actorId) {
7611
7613
  return Object.values(snapshot.endpoints).filter((endpoint) => endpoint.agentId === actorId).sort((lhs, rhs) => lhs.id.localeCompare(rhs.id))[0];
7612
7614
  }
7613
- function buildScoutReturnAddress(snapshot, actorId, options = {}) {
7615
+ function buildScoutReturnAddress2(snapshot, actorId, options = {}) {
7614
7616
  const agent = snapshot.agents[actorId];
7615
7617
  const actor = snapshot.actors[actorId];
7616
7618
  const endpoint = firstEndpointForActor(snapshot, actorId);
7617
7619
  const selector = agent?.selector?.trim() || metadataString2(agent?.metadata, "selector") || metadataString2(actor?.metadata, "selector");
7618
7620
  const defaultSelector = agent?.defaultSelector?.trim() || metadataString2(agent?.metadata, "defaultSelector") || metadataString2(actor?.metadata, "defaultSelector");
7619
7621
  const projectRoot = endpoint?.projectRoot ?? endpoint?.cwd ?? metadataString2(agent?.metadata, "projectRoot") ?? metadataString2(actor?.metadata, "projectRoot");
7620
- return buildRelayReturnAddress({
7622
+ return buildScoutReturnAddress({
7621
7623
  actorId,
7622
7624
  handle: agent?.handle?.trim() || actor?.handle?.trim() || actorId,
7623
7625
  displayName: agent?.displayName || actor?.displayName,
@@ -7776,7 +7778,9 @@ async function resolveMentionTargets(snapshot, text, currentDirectory) {
7776
7778
  const unresolved = [...mentions.unparsed];
7777
7779
  const ambiguous = [];
7778
7780
  const candidateMap = new Map;
7779
- const endpointBackedAgentIds = [...new Set(Object.values(snapshot.endpoints).map((endpoint) => endpoint.agentId).filter((agentId) => agentId && agentId !== OPERATOR_ID))];
7781
+ const endpointBackedAgentIds = [
7782
+ ...new Set(Object.values(snapshot.endpoints).map((endpoint) => endpoint.agentId).filter((agentId) => agentId && agentId !== OPERATOR_ID))
7783
+ ];
7780
7784
  for (const agent of Object.values(snapshot.agents)) {
7781
7785
  if (isSupersededBrokerAgent(snapshot, agent.id)) {
7782
7786
  continue;
@@ -7786,14 +7790,19 @@ async function resolveMentionTargets(snapshot, text, currentDirectory) {
7786
7790
  for (const selector of selectors) {
7787
7791
  if (selector.definitionId === "system")
7788
7792
  continue;
7789
- const discovered = await resolveRelayAgentConfig(selector, { currentDirectory });
7793
+ const discovered = await resolveRelayAgentConfig(selector, {
7794
+ currentDirectory
7795
+ });
7790
7796
  if (discovered && !candidateMap.has(discovered.agentId)) {
7791
7797
  candidateMap.set(discovered.agentId, {
7792
7798
  agentId: discovered.agentId,
7793
7799
  definitionId: discovered.definitionId,
7794
7800
  nodeQualifier: discovered.instance.nodeQualifier,
7795
7801
  workspaceQualifier: discovered.instance.workspaceQualifier,
7796
- aliases: [discovered.instance.selector, discovered.instance.defaultSelector]
7802
+ aliases: [
7803
+ discovered.instance.selector,
7804
+ discovered.instance.defaultSelector
7805
+ ]
7797
7806
  });
7798
7807
  }
7799
7808
  const candidates = Array.from(candidateMap.values());
@@ -8033,8 +8042,12 @@ async function ensureTargetRelayAgentRegistered(baseUrl, snapshot, nodeId, agent
8033
8042
  }
8034
8043
  function conversationDefinition(snapshot, nodeId, channel, senderId, targetParticipantIds = []) {
8035
8044
  const normalizedChannel = channel?.trim() || "shared";
8036
- const sharedParticipants = [...new Set([OPERATOR_ID, senderId, ...Object.keys(snapshot.agents)])].sort();
8037
- const scopedParticipants = [...new Set([OPERATOR_ID, senderId, ...targetParticipantIds])].sort();
8045
+ const sharedParticipants = [
8046
+ ...new Set([OPERATOR_ID, senderId, ...Object.keys(snapshot.agents)])
8047
+ ].sort();
8048
+ const scopedParticipants = [
8049
+ ...new Set([OPERATOR_ID, senderId, ...targetParticipantIds])
8050
+ ].sort();
8038
8051
  if (normalizedChannel === "voice") {
8039
8052
  return {
8040
8053
  id: BROKER_VOICE_CHANNEL_ID,
@@ -8085,7 +8098,12 @@ function conversationDefinition(snapshot, nodeId, channel, senderId, targetParti
8085
8098
  async function ensureBrokerConversation(baseUrl, snapshot, nodeId, channel, senderId, targetParticipantIds = []) {
8086
8099
  const definition = conversationDefinition(snapshot, nodeId, channel, senderId, targetParticipantIds);
8087
8100
  const existing = snapshot.conversations[definition.id];
8088
- const nextParticipants = [...new Set([...existing?.participantIds ?? [], ...definition.participantIds])].sort();
8101
+ const nextParticipants = [
8102
+ ...new Set([
8103
+ ...existing?.participantIds ?? [],
8104
+ ...definition.participantIds
8105
+ ])
8106
+ ].sort();
8089
8107
  if (!existing || existing.kind !== definition.kind || existing.visibility !== definition.visibility || existing.shareMode !== definition.shareMode || nextParticipants.length !== existing.participantIds.length) {
8090
8108
  const nextConversation = {
8091
8109
  ...definition,
@@ -8107,6 +8125,221 @@ function directConversationIdForActors(sourceId, targetId) {
8107
8125
  }
8108
8126
  return `dm.${[sourceId, targetId].sort().join(".")}`;
8109
8127
  }
8128
+ function relayChannelMetadata(conversation, explicitChannel) {
8129
+ const normalized = explicitChannel?.trim();
8130
+ if (normalized) {
8131
+ return normalized;
8132
+ }
8133
+ return conversation.kind === "direct" ? "dm" : "shared";
8134
+ }
8135
+ function relayAudienceReason(conversation) {
8136
+ return conversation.kind === "direct" ? "direct_message" : "mention";
8137
+ }
8138
+ function buildScoutEntityId(prefix, createdAtMs) {
8139
+ return `${prefix}-${createdAtMs.toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
8140
+ }
8141
+ function createTrackedWorkItemSummary(record) {
8142
+ if (record.kind !== "work_item") {
8143
+ throw new Error(`expected work_item collaboration record, received ${record.kind}`);
8144
+ }
8145
+ return {
8146
+ id: record.id,
8147
+ title: record.title,
8148
+ summary: record.summary ?? null,
8149
+ state: record.state,
8150
+ acceptanceState: record.acceptanceState,
8151
+ ownerId: record.ownerId ?? null,
8152
+ nextMoveOwnerId: record.nextMoveOwnerId ?? null,
8153
+ conversationId: record.conversationId ?? null,
8154
+ priority: record.priority ?? null
8155
+ };
8156
+ }
8157
+ async function createScoutTrackedWorkItem(input) {
8158
+ const recordId = buildScoutEntityId("work", input.createdAtMs);
8159
+ const record = {
8160
+ id: recordId,
8161
+ kind: "work_item",
8162
+ state: "open",
8163
+ acceptanceState: input.workItem.acceptanceState ?? "pending",
8164
+ title: input.workItem.title.trim(),
8165
+ summary: input.workItem.summary?.trim() || undefined,
8166
+ createdById: input.senderId,
8167
+ ownerId: input.targetAgentId,
8168
+ nextMoveOwnerId: input.targetAgentId,
8169
+ conversationId: input.conversationId,
8170
+ parentId: input.workItem.parentId?.trim() || undefined,
8171
+ priority: input.workItem.priority,
8172
+ labels: input.workItem.labels?.map((label) => label.trim()).filter(Boolean),
8173
+ createdAt: input.createdAtMs,
8174
+ updatedAt: input.createdAtMs,
8175
+ requestedById: input.senderId,
8176
+ metadata: {
8177
+ source: input.source,
8178
+ ...input.workItem.metadata ?? {}
8179
+ }
8180
+ };
8181
+ await brokerPostJson(input.baseUrl, scoutBrokerPaths.v1.collaborationRecords, record);
8182
+ const event = {
8183
+ id: buildScoutEntityId("evt", input.createdAtMs),
8184
+ recordId,
8185
+ recordKind: "work_item",
8186
+ kind: "created",
8187
+ actorId: input.senderId,
8188
+ at: input.createdAtMs,
8189
+ summary: input.workItem.summary?.trim() || input.workItem.title.trim(),
8190
+ metadata: {
8191
+ source: input.source
8192
+ }
8193
+ };
8194
+ await brokerPostJson(input.baseUrl, scoutBrokerPaths.v1.collaborationEvents, event);
8195
+ return createTrackedWorkItemSummary(record);
8196
+ }
8197
+ function normalizeOptionalString2(value) {
8198
+ if (value === null || value === undefined) {
8199
+ return;
8200
+ }
8201
+ const trimmed = value.trim();
8202
+ return trimmed.length > 0 ? trimmed : undefined;
8203
+ }
8204
+ function normalizeWorkItemLabels(labels) {
8205
+ if (!labels) {
8206
+ return;
8207
+ }
8208
+ const normalized = labels.map((label) => label.trim()).filter(Boolean);
8209
+ return normalized.length > 0 ? normalized : undefined;
8210
+ }
8211
+ function normalizeWorkItemProgress(progress) {
8212
+ if (!progress) {
8213
+ return;
8214
+ }
8215
+ const normalized = {};
8216
+ if (typeof progress.completedSteps === "number") {
8217
+ normalized.completedSteps = progress.completedSteps;
8218
+ }
8219
+ if (typeof progress.totalSteps === "number") {
8220
+ normalized.totalSteps = progress.totalSteps;
8221
+ }
8222
+ if (typeof progress.percent === "number") {
8223
+ normalized.percent = progress.percent;
8224
+ }
8225
+ if (typeof progress.checkpoint === "string" && progress.checkpoint.trim()) {
8226
+ normalized.checkpoint = progress.checkpoint.trim();
8227
+ }
8228
+ if (typeof progress.summary === "string" && progress.summary.trim()) {
8229
+ normalized.summary = progress.summary.trim();
8230
+ }
8231
+ return Object.keys(normalized).length > 0 ? normalized : undefined;
8232
+ }
8233
+ function normalizeWorkItemWaitingOn(waitingOn) {
8234
+ if (!waitingOn) {
8235
+ return;
8236
+ }
8237
+ const label = waitingOn.label.trim();
8238
+ if (!label) {
8239
+ return;
8240
+ }
8241
+ return {
8242
+ ...waitingOn,
8243
+ label,
8244
+ targetId: normalizeOptionalString2(waitingOn.targetId)
8245
+ };
8246
+ }
8247
+ function deriveWorkItemEventKind(previous, next) {
8248
+ if (next.acceptanceState !== previous.acceptanceState) {
8249
+ if (next.acceptanceState === "accepted") {
8250
+ return "accepted";
8251
+ }
8252
+ if (next.acceptanceState === "reopened") {
8253
+ return "reopened";
8254
+ }
8255
+ }
8256
+ if (next.state !== previous.state) {
8257
+ switch (next.state) {
8258
+ case "waiting":
8259
+ return "waiting";
8260
+ case "review":
8261
+ return "review_requested";
8262
+ case "done":
8263
+ return "done";
8264
+ case "cancelled":
8265
+ return "cancelled";
8266
+ case "working":
8267
+ return previous.state === "open" ? "claimed" : "progressed";
8268
+ case "open":
8269
+ default:
8270
+ return "progressed";
8271
+ }
8272
+ }
8273
+ if (next.ownerId !== previous.ownerId || next.nextMoveOwnerId !== previous.nextMoveOwnerId) {
8274
+ return "handoff";
8275
+ }
8276
+ return "progressed";
8277
+ }
8278
+ function summarizeWorkItemUpdate(record) {
8279
+ if (record.progress?.summary?.trim()) {
8280
+ return record.progress.summary.trim();
8281
+ }
8282
+ if (record.summary?.trim()) {
8283
+ return record.summary.trim();
8284
+ }
8285
+ return record.title.trim();
8286
+ }
8287
+ function brokerSnapshotWorkItem(snapshot, workId) {
8288
+ const record = snapshot.collaborationRecords[workId];
8289
+ return record?.kind === "work_item" ? record : null;
8290
+ }
8291
+ async function updateScoutWorkItem(input) {
8292
+ const broker = await loadScoutBrokerContext();
8293
+ if (!broker) {
8294
+ return null;
8295
+ }
8296
+ const current = brokerSnapshotWorkItem(broker.snapshot, input.workId.trim());
8297
+ if (!current) {
8298
+ throw new Error(`unknown work item: ${input.workId}`);
8299
+ }
8300
+ const updatedAtMs = input.updatedAtMs ?? Date.now();
8301
+ const nextState = input.state ?? current.state;
8302
+ const nextSummary = input.summary === undefined ? current.summary : normalizeOptionalString2(input.summary) ?? undefined;
8303
+ const nextOwnerId = input.ownerId === undefined ? current.ownerId : normalizeOptionalString2(input.ownerId);
8304
+ const nextMoveOwnerId = input.nextMoveOwnerId === undefined ? current.nextMoveOwnerId : normalizeOptionalString2(input.nextMoveOwnerId);
8305
+ const nextPriority = input.priority === undefined ? current.priority : input.priority ?? undefined;
8306
+ const nextLabels = input.labels === undefined ? current.labels : normalizeWorkItemLabels(input.labels);
8307
+ const nextProgress = input.progress === undefined ? current.progress : normalizeWorkItemProgress(input.progress);
8308
+ const waitingOn = input.waitingOn === undefined ? nextState === "waiting" ? current.waitingOn : undefined : normalizeWorkItemWaitingOn(input.waitingOn);
8309
+ const updated = {
8310
+ ...current,
8311
+ title: normalizeOptionalString2(input.title) ?? current.title,
8312
+ summary: nextSummary,
8313
+ state: nextState,
8314
+ acceptanceState: input.acceptanceState ?? current.acceptanceState,
8315
+ ownerId: nextOwnerId,
8316
+ nextMoveOwnerId,
8317
+ priority: nextPriority,
8318
+ labels: nextLabels,
8319
+ waitingOn,
8320
+ progress: nextProgress,
8321
+ updatedAt: updatedAtMs,
8322
+ startedAt: current.startedAt ?? (nextState === "working" ? updatedAtMs : current.startedAt),
8323
+ reviewRequestedAt: nextState === "review" ? current.reviewRequestedAt ?? updatedAtMs : current.reviewRequestedAt,
8324
+ completedAt: nextState === "done" || nextState === "cancelled" ? current.completedAt ?? updatedAtMs : current.completedAt,
8325
+ metadata: input.metadata ? { ...current.metadata ?? {}, ...input.metadata } : current.metadata
8326
+ };
8327
+ await brokerPostJson(broker.baseUrl, scoutBrokerPaths.v1.collaborationRecords, updated);
8328
+ const event = {
8329
+ id: buildScoutEntityId("evt", updatedAtMs),
8330
+ recordId: updated.id,
8331
+ recordKind: "work_item",
8332
+ kind: deriveWorkItemEventKind(current, updated),
8333
+ actorId: input.actorId,
8334
+ at: updatedAtMs,
8335
+ summary: normalizeOptionalString2(input.eventSummary) ?? summarizeWorkItemUpdate(updated),
8336
+ metadata: {
8337
+ source: input.source?.trim() || "scout-mcp"
8338
+ }
8339
+ };
8340
+ await brokerPostJson(broker.baseUrl, scoutBrokerPaths.v1.collaborationEvents, event);
8341
+ return createTrackedWorkItemSummary(updated);
8342
+ }
8110
8343
  async function ensureBrokerDirectConversationBetween(baseUrl, snapshot, nodeId, sourceId, targetId) {
8111
8344
  const conversationId = targetId === SCOUT_AGENT_ID && sourceId === OPERATOR_ID ? BROKER_SHARED_CHANNEL_ID : directConversationIdForActors(sourceId, targetId);
8112
8345
  const participantIds = [...new Set([sourceId, targetId])].sort();
@@ -8154,7 +8387,9 @@ async function sendScoutMessage(input) {
8154
8387
  const mentionResolution = await resolveMentionTargets(broker.snapshot, input.body, currentDirectory);
8155
8388
  const senderId = await resolveConversationActorId(broker.baseUrl, broker.snapshot, broker.node.id, input.senderId, currentDirectory);
8156
8389
  const availableTargets = (await Promise.all(mentionResolution.resolved.map(async (target) => await ensureTargetRelayAgentRegistered(broker.baseUrl, broker.snapshot, broker.node.id, target.agentId, currentDirectory) ? target : null))).filter((target) => Boolean(target));
8157
- const validTargets = [...new Set(availableTargets.map((target) => target.agentId).filter((target) => target !== senderId && Boolean(broker.snapshot.agents[target])))].sort();
8390
+ const validTargets = [
8391
+ ...new Set(availableTargets.map((target) => target.agentId).filter((target) => target !== senderId && Boolean(broker.snapshot.agents[target])))
8392
+ ].sort();
8158
8393
  const unresolvedTargets = mentionResolution.resolved.filter((target) => !validTargets.includes(target.agentId)).map((target) => target.label).concat(mentionResolution.unresolved).concat(mentionResolution.ambiguous.map((entry) => entry.label));
8159
8394
  if (unresolvedTargets.length > 0) {
8160
8395
  return { usedBroker: true, invokedTargets: [], unresolvedTargets };
@@ -8168,7 +8403,7 @@ async function sendScoutMessage(input) {
8168
8403
  }
8169
8404
  const messageId = `m-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
8170
8405
  const speechText = input.shouldSpeak ? stripScoutAgentSelectorLabels(input.body) : "";
8171
- const returnAddress = buildScoutReturnAddress(broker.snapshot, senderId, {
8406
+ const returnAddress = buildScoutReturnAddress2(broker.snapshot, senderId, {
8172
8407
  conversationId: conversation.id,
8173
8408
  replyToMessageId: messageId
8174
8409
  });
@@ -8181,18 +8416,25 @@ async function sendScoutMessage(input) {
8181
8416
  body: input.body,
8182
8417
  mentions: mentionResolution.resolved.filter((target) => validTargets.includes(target.agentId)).map((target) => ({ actorId: target.agentId, label: target.label })),
8183
8418
  speech: speechText ? { text: speechText } : undefined,
8184
- audience: validTargets.length > 0 ? { notify: validTargets, reason: "mention" } : undefined,
8419
+ audience: validTargets.length > 0 ? { notify: validTargets, reason: relayAudienceReason(conversation) } : undefined,
8185
8420
  visibility: conversation.visibility,
8186
8421
  policy: "durable",
8187
8422
  createdAt: createdAtMs,
8188
8423
  metadata: {
8189
8424
  source: "scout-cli",
8190
- relayChannel: input.channel ?? "shared",
8425
+ relayChannel: relayChannelMetadata(conversation, input.channel),
8426
+ relayTargetIds: validTargets,
8191
8427
  relayMessageId: messageId,
8192
8428
  returnAddress
8193
8429
  }
8194
8430
  });
8195
- return { usedBroker: true, invokedTargets: validTargets, unresolvedTargets };
8431
+ return {
8432
+ usedBroker: true,
8433
+ conversationId: conversation.id,
8434
+ messageId,
8435
+ invokedTargets: validTargets,
8436
+ unresolvedTargets
8437
+ };
8196
8438
  }
8197
8439
  async function sendScoutMessageToAgentIds(input) {
8198
8440
  const broker = await loadScoutBrokerContext();
@@ -8207,7 +8449,9 @@ async function sendScoutMessageToAgentIds(input) {
8207
8449
  const createdAtMs = input.createdAtMs ?? Date.now();
8208
8450
  const source = input.source?.trim() || "scout-mcp";
8209
8451
  const senderId = await resolveConversationActorId(broker.baseUrl, broker.snapshot, broker.node.id, input.senderId, currentDirectory);
8210
- const requestedTargetIds = [...new Set(input.targetAgentIds.map((targetId) => targetId.trim()).filter(Boolean).filter((targetId) => targetId !== senderId))];
8452
+ const requestedTargetIds = [
8453
+ ...new Set(input.targetAgentIds.map((targetId) => targetId.trim()).filter(Boolean).filter((targetId) => targetId !== senderId))
8454
+ ];
8211
8455
  const availableTargets = (await Promise.all(requestedTargetIds.map(async (targetId) => await ensureTargetRelayAgentRegistered(broker.baseUrl, broker.snapshot, broker.node.id, targetId, currentDirectory) ? targetId : null))).filter((targetId) => Boolean(targetId && broker.snapshot.agents[targetId]));
8212
8456
  const unresolvedTargetIds = requestedTargetIds.filter((targetId) => !availableTargets.includes(targetId));
8213
8457
  if (unresolvedTargetIds.length > 0) {
@@ -8226,7 +8470,7 @@ async function sendScoutMessageToAgentIds(input) {
8226
8470
  }
8227
8471
  const messageId = `m-${createdAtMs.toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
8228
8472
  const speechText = input.shouldSpeak ? input.body.trim() : "";
8229
- const returnAddress = buildScoutReturnAddress(broker.snapshot, senderId, {
8473
+ const returnAddress = buildScoutReturnAddress2(broker.snapshot, senderId, {
8230
8474
  conversationId: conversation.id,
8231
8475
  replyToMessageId: messageId
8232
8476
  });
@@ -8244,14 +8488,14 @@ async function sendScoutMessageToAgentIds(input) {
8244
8488
  speech: speechText ? { text: speechText } : undefined,
8245
8489
  audience: availableTargets.length > 0 ? {
8246
8490
  notify: availableTargets,
8247
- reason: conversation.kind === "direct" ? "direct_message" : "mention"
8491
+ reason: relayAudienceReason(conversation)
8248
8492
  } : undefined,
8249
8493
  visibility: conversation.visibility,
8250
8494
  policy: "durable",
8251
8495
  createdAt: createdAtMs,
8252
8496
  metadata: {
8253
8497
  source,
8254
- relayChannel: input.channel ?? (conversation.kind === "direct" ? "dm" : "shared"),
8498
+ relayChannel: relayChannelMetadata(conversation, input.channel),
8255
8499
  relayTargetIds: availableTargets,
8256
8500
  relayMessageId: messageId,
8257
8501
  returnAddress
@@ -8297,7 +8541,7 @@ async function sendScoutDirectMessage(input) {
8297
8541
  const targetAgentId = directSession.targetId;
8298
8542
  const targetAgent = broker.snapshot.agents[targetAgentId] ?? ("agent" in directSession ? directSession.agent : undefined);
8299
8543
  const targetLabel = `@${targetAgent?.handle?.trim() || targetAgent?.displayName?.trim() || targetAgentId}`;
8300
- const returnAddress = buildScoutReturnAddress(broker.snapshot, OPERATOR_ID, {
8544
+ const returnAddress = buildScoutReturnAddress2(broker.snapshot, OPERATOR_ID, {
8301
8545
  conversationId: directSession.conversation.id,
8302
8546
  replyToMessageId: messageId
8303
8547
  });
@@ -8375,8 +8619,12 @@ async function askScoutAgentById(input) {
8375
8619
  raw: targetLabel.replace(/^@/, ""),
8376
8620
  label: targetLabel,
8377
8621
  definitionId: broker.snapshot.agents[targetAgentId]?.definitionId ?? metadataString2(broker.snapshot.agents[targetAgentId]?.metadata, "definitionId") ?? targetAgentId,
8378
- ...broker.snapshot.agents[targetAgentId]?.workspaceQualifier ? { workspaceQualifier: broker.snapshot.agents[targetAgentId]?.workspaceQualifier } : {},
8379
- ...broker.snapshot.agents[targetAgentId]?.nodeQualifier ? { nodeQualifier: broker.snapshot.agents[targetAgentId]?.nodeQualifier } : {}
8622
+ ...broker.snapshot.agents[targetAgentId]?.workspaceQualifier ? {
8623
+ workspaceQualifier: broker.snapshot.agents[targetAgentId]?.workspaceQualifier
8624
+ } : {},
8625
+ ...broker.snapshot.agents[targetAgentId]?.nodeQualifier ? {
8626
+ nodeQualifier: broker.snapshot.agents[targetAgentId]?.nodeQualifier
8627
+ } : {}
8380
8628
  }
8381
8629
  };
8382
8630
  const targetReady = await ensureTargetRelayAgentRegistered(broker.baseUrl, broker.snapshot, broker.node.id, targetAgentId, currentDirectory);
@@ -8396,10 +8644,19 @@ async function askScoutAgentById(input) {
8396
8644
  }
8397
8645
  const messageId = `m-${createdAtMs.toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
8398
8646
  const speechText = input.shouldSpeak ? input.body.trim() : "";
8399
- const returnAddress = buildScoutReturnAddress(broker.snapshot, senderId, {
8647
+ const returnAddress = buildScoutReturnAddress2(broker.snapshot, senderId, {
8400
8648
  conversationId: conversation.id,
8401
8649
  replyToMessageId: messageId
8402
8650
  });
8651
+ const workItem = input.workItem ? await createScoutTrackedWorkItem({
8652
+ baseUrl: broker.baseUrl,
8653
+ senderId,
8654
+ targetAgentId,
8655
+ conversationId: conversation.id,
8656
+ createdAtMs,
8657
+ source,
8658
+ workItem: input.workItem
8659
+ }) : undefined;
8403
8660
  await brokerPostJson(broker.baseUrl, scoutBrokerPaths.v1.messages, {
8404
8661
  id: messageId,
8405
8662
  conversationId: conversation.id,
@@ -8411,15 +8668,16 @@ async function askScoutAgentById(input) {
8411
8668
  speech: speechText ? { text: speechText } : undefined,
8412
8669
  audience: {
8413
8670
  notify: [targetAgentId],
8414
- reason: conversation.kind === "direct" ? "direct_message" : "mention"
8671
+ reason: relayAudienceReason(conversation)
8415
8672
  },
8416
8673
  visibility: conversation.visibility,
8417
8674
  policy: "durable",
8418
8675
  createdAt: createdAtMs,
8419
8676
  metadata: {
8420
8677
  source,
8421
- relayChannel: input.channel ?? (conversation.kind === "direct" ? "dm" : "shared"),
8678
+ relayChannel: relayChannelMetadata(conversation, input.channel),
8422
8679
  relayTarget: targetAgentId,
8680
+ collaborationRecordId: workItem?.id,
8423
8681
  returnAddress
8424
8682
  }
8425
8683
  });
@@ -8430,6 +8688,7 @@ async function askScoutAgentById(input) {
8430
8688
  targetAgentId,
8431
8689
  action: "consult",
8432
8690
  task: input.body.trim(),
8691
+ collaborationRecordId: workItem?.id,
8433
8692
  conversationId: conversation.id,
8434
8693
  messageId,
8435
8694
  execution: input.executionHarness ? { harness: input.executionHarness } : undefined,
@@ -8438,8 +8697,9 @@ async function askScoutAgentById(input) {
8438
8697
  createdAt: createdAtMs,
8439
8698
  metadata: {
8440
8699
  source,
8441
- relayChannel: input.channel ?? (conversation.kind === "direct" ? "dm" : "shared"),
8700
+ relayChannel: relayChannelMetadata(conversation, input.channel),
8442
8701
  relayTarget: targetAgentId,
8702
+ collaborationRecordId: workItem?.id,
8443
8703
  returnAddress
8444
8704
  }
8445
8705
  });
@@ -8447,7 +8707,8 @@ async function askScoutAgentById(input) {
8447
8707
  usedBroker: true,
8448
8708
  flight: invocationResponse.flight,
8449
8709
  conversationId: conversation.id,
8450
- messageId
8710
+ messageId,
8711
+ workItem
8451
8712
  };
8452
8713
  }
8453
8714
  async function askScoutQuestion(input) {
@@ -8490,10 +8751,20 @@ async function askScoutQuestion(input) {
8490
8751
  const messageId = `m-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
8491
8752
  const messageBody = input.body.trim().startsWith(target.label) ? input.body.trim() : `${target.label} ${input.body.trim()}`;
8492
8753
  const speechText = input.shouldSpeak ? stripScoutAgentSelectorLabels(messageBody) : "";
8493
- const returnAddress = buildScoutReturnAddress(broker.snapshot, senderId, {
8754
+ const createdAt = input.createdAtMs ?? Date.now();
8755
+ const returnAddress = buildScoutReturnAddress2(broker.snapshot, senderId, {
8494
8756
  conversationId: conversation.id,
8495
8757
  replyToMessageId: messageId
8496
8758
  });
8759
+ const workItem = input.workItem ? await createScoutTrackedWorkItem({
8760
+ baseUrl: broker.baseUrl,
8761
+ senderId,
8762
+ targetAgentId: target.agentId,
8763
+ conversationId: conversation.id,
8764
+ createdAtMs: createdAt,
8765
+ source: "scout-cli",
8766
+ workItem: input.workItem
8767
+ }) : undefined;
8497
8768
  await brokerPostJson(broker.baseUrl, scoutBrokerPaths.v1.messages, {
8498
8769
  id: messageId,
8499
8770
  conversationId: conversation.id,
@@ -8503,14 +8774,18 @@ async function askScoutQuestion(input) {
8503
8774
  body: messageBody,
8504
8775
  mentions: [{ actorId: target.agentId, label: target.label }],
8505
8776
  speech: speechText ? { text: speechText } : undefined,
8506
- audience: { notify: [target.agentId], reason: "mention" },
8777
+ audience: {
8778
+ notify: [target.agentId],
8779
+ reason: relayAudienceReason(conversation)
8780
+ },
8507
8781
  visibility: conversation.visibility,
8508
8782
  policy: "durable",
8509
- createdAt: input.createdAtMs ?? Date.now(),
8783
+ createdAt,
8510
8784
  metadata: {
8511
8785
  source: "scout-cli",
8512
- relayChannel: input.channel ?? (conversation.kind === "direct" ? "dm" : "shared"),
8786
+ relayChannel: relayChannelMetadata(conversation, input.channel),
8513
8787
  relayTarget: target.agentId,
8788
+ collaborationRecordId: workItem?.id,
8514
8789
  returnAddress
8515
8790
  }
8516
8791
  });
@@ -8521,16 +8796,18 @@ async function askScoutQuestion(input) {
8521
8796
  targetAgentId: target.agentId,
8522
8797
  action: "consult",
8523
8798
  task: messageBody,
8799
+ collaborationRecordId: workItem?.id,
8524
8800
  conversationId: conversation.id,
8525
8801
  messageId,
8526
8802
  execution: input.executionHarness ? { harness: input.executionHarness } : undefined,
8527
8803
  ensureAwake: true,
8528
8804
  stream: false,
8529
- createdAt: Date.now(),
8805
+ createdAt,
8530
8806
  metadata: {
8531
8807
  source: "scout-cli",
8532
- relayChannel: input.channel ?? (conversation.kind === "direct" ? "dm" : "shared"),
8808
+ relayChannel: relayChannelMetadata(conversation, input.channel),
8533
8809
  relayTarget: target.agentId,
8810
+ collaborationRecordId: workItem?.id,
8534
8811
  returnAddress
8535
8812
  }
8536
8813
  });
@@ -8538,7 +8815,8 @@ async function askScoutQuestion(input) {
8538
8815
  usedBroker: true,
8539
8816
  flight: invocationResponse.flight,
8540
8817
  conversationId: conversation.id,
8541
- messageId
8818
+ messageId,
8819
+ workItem
8542
8820
  };
8543
8821
  }
8544
8822
  async function loadBrokerFlight(baseUrl, flightId) {
@@ -8734,17 +9012,25 @@ async function listScoutAgents(options = {}) {
8734
9012
  continue;
8735
9013
  if (isSupersededBrokerAgent(broker.snapshot, message.actorId))
8736
9014
  continue;
8737
- const current = messageStats.get(message.actorId) ?? { messages: 0, lastSeen: null };
9015
+ const current = messageStats.get(message.actorId) ?? {
9016
+ messages: 0,
9017
+ lastSeen: null
9018
+ };
8738
9019
  current.messages += 1;
8739
- current.lastSeen = maxDefined([current.lastSeen, normalizeUnixTimestamp(message.createdAt)]);
9020
+ current.lastSeen = maxDefined([
9021
+ current.lastSeen,
9022
+ normalizeUnixTimestamp(message.createdAt)
9023
+ ]);
8740
9024
  messageStats.set(message.actorId, current);
8741
9025
  }
8742
- return [...new Set([
8743
- ...Object.keys(broker.snapshot.agents ?? {}),
8744
- ...Array.from(endpointsByAgent.keys()),
8745
- ...Array.from(messageStats.keys()),
8746
- ...Array.from(configuredAgentIds.values())
8747
- ])].filter((agentId) => agentId && agentId !== OPERATOR_ID).filter((agentId) => !isSupersededBrokerAgent(broker.snapshot, agentId)).map((agentId) => {
9026
+ return [
9027
+ ...new Set([
9028
+ ...Object.keys(broker.snapshot.agents ?? {}),
9029
+ ...Array.from(endpointsByAgent.keys()),
9030
+ ...Array.from(messageStats.keys()),
9031
+ ...Array.from(configuredAgentIds.values())
9032
+ ])
9033
+ ].filter((agentId) => agentId && agentId !== OPERATOR_ID).filter((agentId) => !isSupersededBrokerAgent(broker.snapshot, agentId)).map((agentId) => {
8748
9034
  const endpoints = endpointsByAgent.get(agentId) ?? [];
8749
9035
  const brokerMessages = messageStats.get(agentId);
8750
9036
  const registrationKind = configuredAgentIds.has(agentId) ? "configured" : "broker";
@@ -8911,6 +9197,12 @@ function renderAmbiguousCandidate(label) {
8911
9197
  return "";
8912
9198
  return trimmed.startsWith("@") ? trimmed : `@${trimmed}`;
8913
9199
  }
9200
+ function renderConversationRoute(conversationId) {
9201
+ if (!conversationId) {
9202
+ return "conversation";
9203
+ }
9204
+ return conversationId.startsWith("dm.") ? `DM ${conversationId}` : `conversation ${conversationId}`;
9205
+ }
8914
9206
  function formatScoutAskRoutingError(result, targetLabel) {
8915
9207
  const renderedTarget = renderScoutTargetLabel(targetLabel);
8916
9208
  const diagnostic = result.targetDiagnostic;
@@ -8956,12 +9248,15 @@ async function runAskWithOptions(context, options) {
8956
9248
  if (!result.flight) {
8957
9249
  throw new Error(formatScoutAskRoutingError(result, options.targetLabel));
8958
9250
  }
8959
- context.stderr(`asking ${result.flight.targetAgentId}... (flight ${result.flight.id})`);
9251
+ context.stderr(`asking ${result.flight.targetAgentId} as ${senderId} via ${renderConversationRoute(result.conversationId)}... (flight ${result.flight.id})`);
8960
9252
  const completed = await waitForScoutFlight(resolveScoutBrokerUrl(), result.flight.id, {
8961
9253
  timeoutSeconds: options.timeoutSeconds,
8962
9254
  onUpdate: (_flight, detail) => context.stderr(detail)
8963
9255
  });
8964
9256
  context.output.writeValue({
9257
+ senderId,
9258
+ conversationId: result.conversationId ?? null,
9259
+ messageId: result.messageId ?? null,
8965
9260
  flight: completed,
8966
9261
  output: completed.output ?? completed.summary ?? ""
8967
9262
  }, (value) => value.output);
@@ -9018,6 +9313,13 @@ function renderScoutAgentList(entries) {
9018
9313
  }
9019
9314
  function renderScoutMessagePostResult(result) {
9020
9315
  const lines = [result.message];
9316
+ if (result.senderId) {
9317
+ lines.push(`From: ${result.senderId}`);
9318
+ }
9319
+ if (result.conversationId) {
9320
+ const route = result.conversationId.startsWith("dm.") ? "DM" : "Conversation";
9321
+ lines.push(`${route}: ${result.conversationId}`);
9322
+ }
9021
9323
  if (result.invokedTargets.length > 0) {
9022
9324
  lines.push(`Routed to: ${result.invokedTargets.join(", ")}`);
9023
9325
  }
@@ -9136,6 +9438,8 @@ async function runSendCommand(context, args) {
9136
9438
  throw new Error(formatScoutSendRoutingError(result.unresolvedTargets));
9137
9439
  }
9138
9440
  context.output.writeValue({
9441
+ senderId,
9442
+ conversationId: result.conversationId,
9139
9443
  message: options.message,
9140
9444
  invokedTargets: result.invokedTargets,
9141
9445
  unresolvedTargets: result.unresolvedTargets
@@ -9185,23 +9489,74 @@ var init_broadcast = __esm(async () => {
9185
9489
  ]);
9186
9490
  });
9187
9491
 
9188
- // ../runtime/src/relay-agent-cards.ts
9492
+ // ../runtime/src/scout-agent-cards.ts
9189
9493
  function metadataString3(metadata, key) {
9190
9494
  const value = metadata?.[key];
9191
9495
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
9192
9496
  }
9193
- function buildRelayAgentCard(binding, options = {}) {
9497
+ function metadataStringArray(metadata, key) {
9498
+ const value = metadata?.[key];
9499
+ if (!Array.isArray(value)) {
9500
+ return;
9501
+ }
9502
+ const next = value.filter((entry) => typeof entry === "string" && entry.trim().length > 0);
9503
+ return next.length > 0 ? next : undefined;
9504
+ }
9505
+ function metadataStringMatrix(metadata, key) {
9506
+ const value = metadata?.[key];
9507
+ if (!Array.isArray(value)) {
9508
+ return;
9509
+ }
9510
+ const next = value.filter((entry) => Array.isArray(entry)).map((entry) => entry.filter((item) => typeof item === "string" && item.trim().length > 0)).filter((entry) => entry.length > 0);
9511
+ return next.length > 0 ? next : undefined;
9512
+ }
9513
+ function metadataRecord2(metadata, key) {
9514
+ const value = metadata?.[key];
9515
+ if (!value || Array.isArray(value) || typeof value !== "object") {
9516
+ return;
9517
+ }
9518
+ return value;
9519
+ }
9520
+ function metadataRecordArray(metadata, key) {
9521
+ const value = metadata?.[key];
9522
+ if (!Array.isArray(value)) {
9523
+ return;
9524
+ }
9525
+ const next = value.filter((entry) => Boolean(entry) && !Array.isArray(entry) && typeof entry === "object");
9526
+ return next.length > 0 ? next : undefined;
9527
+ }
9528
+ function buildScoutAgentCard(binding, options = {}) {
9194
9529
  const projectRoot = binding.endpoint.projectRoot ?? metadataString3(binding.agent.metadata, "projectRoot") ?? binding.endpoint.cwd ?? process.cwd();
9195
9530
  const currentDirectory = options.currentDirectory?.trim() || projectRoot;
9196
9531
  const handle = binding.agent.handle?.trim() || binding.agent.definitionId;
9197
9532
  const selector = binding.agent.selector?.trim() || metadataString3(binding.agent.metadata, "selector");
9198
9533
  const defaultSelector = binding.agent.defaultSelector?.trim() || metadataString3(binding.agent.metadata, "defaultSelector");
9199
9534
  const branch = metadataString3(binding.agent.metadata, "branch") || metadataString3(binding.endpoint.metadata, "branch");
9535
+ const description = metadataString3(binding.agent.metadata, "description");
9536
+ const version = metadataString3(binding.agent.metadata, "version");
9537
+ const documentationUrl = metadataString3(binding.agent.metadata, "documentationUrl") || metadataString3(binding.agent.metadata, "docsUrl");
9538
+ const provider = metadataRecord2(binding.agent.metadata, "provider");
9539
+ const skills = metadataRecordArray(binding.agent.metadata, "skills");
9540
+ const defaultInputModes = metadataStringArray(binding.agent.metadata, "defaultInputModes");
9541
+ const defaultOutputModes = metadataStringArray(binding.agent.metadata, "defaultOutputModes");
9542
+ const supportedInterfaces = metadataRecordArray(binding.agent.metadata, "supportedInterfaces");
9543
+ const securitySchemes = metadataRecord2(binding.agent.metadata, "securitySchemes");
9544
+ const securityRequirements = metadataStringMatrix(binding.agent.metadata, "securityRequirements");
9200
9545
  return {
9201
9546
  id: binding.agent.id,
9202
9547
  agentId: binding.agent.id,
9203
9548
  definitionId: binding.agent.definitionId,
9204
9549
  displayName: binding.agent.displayName,
9550
+ ...description ? { description } : {},
9551
+ ...provider ? { provider } : {},
9552
+ ...version ? { version } : {},
9553
+ ...documentationUrl ? { documentationUrl } : {},
9554
+ ...skills ? { skills } : {},
9555
+ ...defaultInputModes ? { defaultInputModes } : {},
9556
+ ...defaultOutputModes ? { defaultOutputModes } : {},
9557
+ ...supportedInterfaces ? { supportedInterfaces } : {},
9558
+ ...securitySchemes ? { securitySchemes } : {},
9559
+ ...securityRequirements ? { securityRequirements } : {},
9205
9560
  handle,
9206
9561
  ...selector ? { selector } : {},
9207
9562
  ...defaultSelector ? { defaultSelector } : {},
@@ -9216,7 +9571,7 @@ function buildRelayAgentCard(binding, options = {}) {
9216
9571
  ...options.createdById?.trim() ? { createdById: options.createdById.trim() } : {},
9217
9572
  brokerRegistered: options.brokerRegistered ?? false,
9218
9573
  ...options.inboxConversationId?.trim() ? { inboxConversationId: options.inboxConversationId.trim() } : {},
9219
- returnAddress: buildRelayReturnAddress({
9574
+ returnAddress: buildScoutReturnAddress({
9220
9575
  actorId: binding.agent.id,
9221
9576
  handle,
9222
9577
  displayName: binding.agent.displayName,
@@ -9238,7 +9593,7 @@ function buildRelayAgentCard(binding, options = {}) {
9238
9593
  }
9239
9594
  };
9240
9595
  }
9241
- var init_relay_agent_cards = __esm(() => {
9596
+ var init_scout_agent_cards = __esm(() => {
9242
9597
  init_src();
9243
9598
  });
9244
9599
 
@@ -9291,7 +9646,7 @@ async function createScoutAgentCard(input) {
9291
9646
  inboxConversationId = session.conversation.id;
9292
9647
  createdById = session.sourceId;
9293
9648
  }
9294
- return buildRelayAgentCard(binding, {
9649
+ return buildScoutAgentCard(binding, {
9295
9650
  currentDirectory,
9296
9651
  createdById,
9297
9652
  brokerRegistered: syncResult?.brokerRegistered ?? false,
@@ -9299,7 +9654,7 @@ async function createScoutAgentCard(input) {
9299
9654
  });
9300
9655
  }
9301
9656
  var init_service2 = __esm(async () => {
9302
- init_relay_agent_cards();
9657
+ init_scout_agent_cards();
9303
9658
  await __promiseAll([
9304
9659
  init_local_agents(),
9305
9660
  init_service()
@@ -9307,13 +9662,16 @@ var init_service2 = __esm(async () => {
9307
9662
  });
9308
9663
 
9309
9664
  // ../../apps/desktop/src/ui/terminal/cards.ts
9310
- function renderRelayAgentCard(card) {
9665
+ function renderScoutAgentCard(card) {
9311
9666
  const lines = [
9312
9667
  `${card.displayName} [@${card.handle}]`,
9313
9668
  `Agent: ${card.agentId}`,
9314
9669
  `Project: ${card.projectRoot}`,
9315
9670
  `Runtime: ${card.harness} via ${card.transport}${card.sessionId ? ` (${card.sessionId})` : ""}`
9316
9671
  ];
9672
+ if (card.description) {
9673
+ lines.push(`About: ${card.description}`);
9674
+ }
9317
9675
  if (card.selector) {
9318
9676
  lines.push(`Selector: ${card.selector}`);
9319
9677
  }
@@ -9330,6 +9688,12 @@ function renderRelayAgentCard(card) {
9330
9688
  if (card.returnAddress.conversationId) {
9331
9689
  lines.push(`Reply-To: ${card.returnAddress.conversationId}`);
9332
9690
  }
9691
+ if (card.skills && card.skills.length > 0) {
9692
+ lines.push(`Skills: ${card.skills.map((skill) => skill.name).join(", ")}`);
9693
+ }
9694
+ if (card.documentationUrl) {
9695
+ lines.push(`Docs: ${card.documentationUrl}`);
9696
+ }
9333
9697
  return lines.join(`
9334
9698
  `);
9335
9699
  }
@@ -9395,7 +9759,7 @@ async function runCardCommand(context, args) {
9395
9759
  currentDirectory: options.currentDirectory,
9396
9760
  createdById: resolveScoutAgentName(options.requesterId)
9397
9761
  });
9398
- context.output.writeValue(card, renderRelayAgentCard);
9762
+ context.output.writeValue(card, renderScoutAgentCard);
9399
9763
  }
9400
9764
  var init_card = __esm(async () => {
9401
9765
  init_context();
@@ -39549,11 +39913,7 @@ function buildIdentityCandidate(entry) {
39549
39913
  ...entry.workspace ? { workspaceQualifier: entry.workspace } : {},
39550
39914
  ...entry.node ? { nodeQualifier: entry.node } : {},
39551
39915
  ...entry.harness ? { harness: entry.harness } : {},
39552
- aliases: [
39553
- entry.selector,
39554
- entry.defaultSelector,
39555
- entry.handle
39556
- ].filter((value) => Boolean(value && value.trim().length > 0))
39916
+ aliases: [entry.selector, entry.defaultSelector, entry.handle].filter((value) => Boolean(value && value.trim().length > 0))
39557
39917
  };
39558
39918
  }
39559
39919
  function decorateAgentLabels(entries) {
@@ -39756,7 +40116,11 @@ async function resolveScoutAgentForMcp(input) {
39756
40116
  const diagnosis = diagnoseAgentIdentity(selector, identityCandidates);
39757
40117
  if (diagnosis.kind === "resolved") {
39758
40118
  const match = candidates.find((candidate) => candidate.agentId === diagnosis.match.agentId) ?? null;
39759
- return { kind: match ? "resolved" : "unresolved", candidate: match, candidates: [] };
40119
+ return {
40120
+ kind: match ? "resolved" : "unresolved",
40121
+ candidate: match,
40122
+ candidates: []
40123
+ };
39760
40124
  }
39761
40125
  if (diagnosis.kind === "ambiguous") {
39762
40126
  const ambiguous = diagnosis.candidates.map((candidate) => candidates.find((entry) => entry.agentId === candidate.agentId)).filter((candidate) => Boolean(candidate));
@@ -39770,8 +40134,22 @@ function defaultScoutMcpDependencies(env) {
39770
40134
  resolveBrokerUrl: () => env.OPENSCOUT_BROKER_URL?.trim() || resolveScoutBrokerUrl(),
39771
40135
  searchAgents: ({ query, currentDirectory, limit }) => searchScoutAgentsForMcp({ query, currentDirectory, limit }),
39772
40136
  resolveAgent: ({ label, currentDirectory }) => resolveScoutAgentForMcp({ label, currentDirectory }),
39773
- sendMessage: ({ senderId, body, channel, shouldSpeak, currentDirectory }) => sendScoutMessage({ senderId, body, channel, shouldSpeak, currentDirectory }),
39774
- sendMessageToAgentIds: ({ senderId, body, targetAgentIds, channel, shouldSpeak, currentDirectory, source }) => sendScoutMessageToAgentIds({
40137
+ sendMessage: ({ senderId, body, channel, shouldSpeak, currentDirectory }) => sendScoutMessage({
40138
+ senderId,
40139
+ body,
40140
+ channel,
40141
+ shouldSpeak,
40142
+ currentDirectory
40143
+ }),
40144
+ sendMessageToAgentIds: ({
40145
+ senderId,
40146
+ body,
40147
+ targetAgentIds,
40148
+ channel,
40149
+ shouldSpeak,
40150
+ currentDirectory,
40151
+ source
40152
+ }) => sendScoutMessageToAgentIds({
39775
40153
  senderId,
39776
40154
  body,
39777
40155
  targetAgentIds,
@@ -39780,23 +40158,43 @@ function defaultScoutMcpDependencies(env) {
39780
40158
  currentDirectory,
39781
40159
  source
39782
40160
  }),
39783
- askQuestion: ({ senderId, targetLabel, body, channel, shouldSpeak, currentDirectory }) => askScoutQuestion({
40161
+ askQuestion: ({
40162
+ senderId,
40163
+ targetLabel,
40164
+ body,
40165
+ workItem,
40166
+ channel,
40167
+ shouldSpeak,
40168
+ currentDirectory
40169
+ }) => askScoutQuestion({
39784
40170
  senderId,
39785
40171
  targetLabel,
39786
40172
  body,
40173
+ workItem,
39787
40174
  channel,
39788
40175
  shouldSpeak,
39789
40176
  currentDirectory
39790
40177
  }),
39791
- askAgentById: ({ senderId, targetAgentId, body, channel, shouldSpeak, currentDirectory, source }) => askScoutAgentById({
40178
+ askAgentById: ({
39792
40179
  senderId,
39793
40180
  targetAgentId,
39794
40181
  body,
40182
+ workItem,
40183
+ channel,
40184
+ shouldSpeak,
40185
+ currentDirectory,
40186
+ source
40187
+ }) => askScoutAgentById({
40188
+ senderId,
40189
+ targetAgentId,
40190
+ body,
40191
+ workItem,
39795
40192
  channel,
39796
40193
  shouldSpeak,
39797
40194
  currentDirectory,
39798
40195
  source
39799
40196
  }),
40197
+ updateWorkItem: (input) => updateScoutWorkItem(input),
39800
40198
  waitForFlight: (baseUrl, flightId, options) => waitForScoutFlight(baseUrl, flightId, options)
39801
40199
  };
39802
40200
  }
@@ -39923,10 +40321,19 @@ function createScoutMcpServer(options) {
39923
40321
  destructiveHint: false,
39924
40322
  openWorldHint: false
39925
40323
  }
39926
- }, async ({ body, currentDirectory, senderId, channel, shouldSpeak, mentionAgentIds }) => {
40324
+ }, async ({
40325
+ body,
40326
+ currentDirectory,
40327
+ senderId,
40328
+ channel,
40329
+ shouldSpeak,
40330
+ mentionAgentIds
40331
+ }) => {
39927
40332
  const resolvedCurrentDirectory = resolveToolCurrentDirectory(currentDirectory, options.defaultCurrentDirectory);
39928
40333
  const resolvedSenderId = await deps.resolveSenderId(senderId, resolvedCurrentDirectory, env);
39929
- const explicitTargetIds = [...new Set((mentionAgentIds ?? []).map((value) => value.trim()).filter(Boolean))];
40334
+ const explicitTargetIds = [
40335
+ ...new Set((mentionAgentIds ?? []).map((value) => value.trim()).filter(Boolean))
40336
+ ];
39930
40337
  if (explicitTargetIds.length > 0) {
39931
40338
  const result2 = await deps.sendMessageToAgentIds({
39932
40339
  senderId: resolvedSenderId,
@@ -39964,8 +40371,8 @@ function createScoutMcpServer(options) {
39964
40371
  senderId: resolvedSenderId,
39965
40372
  mode: "body_mentions",
39966
40373
  usedBroker: result.usedBroker,
39967
- conversationId: null,
39968
- messageId: null,
40374
+ conversationId: result.conversationId ?? null,
40375
+ messageId: result.messageId ?? null,
39969
40376
  invokedTargetIds: result.invokedTargets,
39970
40377
  unresolvedTargetIds: result.unresolvedTargets
39971
40378
  };
@@ -39976,13 +40383,14 @@ function createScoutMcpServer(options) {
39976
40383
  });
39977
40384
  server.registerTool("invocations_ask", {
39978
40385
  title: "Ask Scout Agent",
39979
- description: "Create a broker-backed Scout invocation. Prefer targetAgentId when the host already resolved an @mention.",
40386
+ description: "Create a broker-backed Scout invocation. Provide workItem to mint a durable workId beyond the message and flight ids.",
39980
40387
  inputSchema: object2({
39981
40388
  body: string2().min(1),
39982
40389
  currentDirectory: string2().optional(),
39983
40390
  senderId: string2().optional(),
39984
40391
  targetAgentId: string2().optional(),
39985
40392
  targetLabel: string2().optional(),
40393
+ workItem: workItemInputSchema.optional(),
39986
40394
  channel: string2().optional(),
39987
40395
  shouldSpeak: boolean2().optional(),
39988
40396
  awaitReply: boolean2().optional(),
@@ -39998,7 +40406,18 @@ function createScoutMcpServer(options) {
39998
40406
  destructiveHint: false,
39999
40407
  openWorldHint: false
40000
40408
  }
40001
- }, async ({ body, currentDirectory, senderId, targetAgentId, targetLabel, channel, shouldSpeak, awaitReply, timeoutSeconds }) => {
40409
+ }, async ({
40410
+ body,
40411
+ currentDirectory,
40412
+ senderId,
40413
+ targetAgentId,
40414
+ targetLabel,
40415
+ workItem,
40416
+ channel,
40417
+ shouldSpeak,
40418
+ awaitReply,
40419
+ timeoutSeconds
40420
+ }) => {
40002
40421
  const resolvedCurrentDirectory = resolveToolCurrentDirectory(currentDirectory, options.defaultCurrentDirectory);
40003
40422
  const resolvedSenderId = await deps.resolveSenderId(senderId, resolvedCurrentDirectory, env);
40004
40423
  const shouldAwait = Boolean(awaitReply);
@@ -40007,6 +40426,7 @@ function createScoutMcpServer(options) {
40007
40426
  senderId: resolvedSenderId,
40008
40427
  targetAgentId: targetAgentId.trim(),
40009
40428
  body,
40429
+ workItem,
40010
40430
  channel,
40011
40431
  shouldSpeak,
40012
40432
  currentDirectory: resolvedCurrentDirectory,
@@ -40023,9 +40443,13 @@ function createScoutMcpServer(options) {
40023
40443
  conversationId: result2.conversationId ?? null,
40024
40444
  messageId: result2.messageId ?? null,
40025
40445
  flight: completedFlight2 ?? result2.flight ?? null,
40446
+ flightId: completedFlight2?.id ?? result2.flight?.id ?? null,
40026
40447
  output: completedFlight2?.output ?? completedFlight2?.summary ?? null,
40027
40448
  unresolvedTargetId: result2.unresolvedTargetId ?? null,
40028
40449
  unresolvedTargetLabel: null,
40450
+ workItem: result2.workItem ?? null,
40451
+ workId: result2.workItem?.id ?? null,
40452
+ workUrl: result2.workItem ? `/api/work/${encodeURIComponent(result2.workItem.id)}` : null,
40029
40453
  targetDiagnostic: result2.targetDiagnostic ?? null
40030
40454
  };
40031
40455
  return {
@@ -40037,6 +40461,7 @@ function createScoutMcpServer(options) {
40037
40461
  senderId: resolvedSenderId,
40038
40462
  targetLabel: targetLabel.trim(),
40039
40463
  body,
40464
+ workItem,
40040
40465
  channel,
40041
40466
  shouldSpeak,
40042
40467
  currentDirectory: resolvedCurrentDirectory
@@ -40052,9 +40477,13 @@ function createScoutMcpServer(options) {
40052
40477
  conversationId: result.conversationId ?? null,
40053
40478
  messageId: result.messageId ?? null,
40054
40479
  flight: completedFlight ?? result.flight ?? null,
40480
+ flightId: completedFlight?.id ?? result.flight?.id ?? null,
40055
40481
  output: completedFlight?.output ?? completedFlight?.summary ?? null,
40056
40482
  unresolvedTargetId: null,
40057
40483
  unresolvedTargetLabel: result.unresolvedTarget ?? null,
40484
+ workItem: result.workItem ?? null,
40485
+ workId: result.workItem?.id ?? null,
40486
+ workUrl: result.workItem ? `/api/work/${encodeURIComponent(result.workItem.id)}` : null,
40058
40487
  targetDiagnostic: result.targetDiagnostic ?? null
40059
40488
  };
40060
40489
  return {
@@ -40062,6 +40491,42 @@ function createScoutMcpServer(options) {
40062
40491
  structuredContent
40063
40492
  };
40064
40493
  });
40494
+ server.registerTool("work_update", {
40495
+ title: "Update Scout Work",
40496
+ description: "Update a durable Scout work item and append a matching collaboration event.",
40497
+ inputSchema: object2({
40498
+ currentDirectory: string2().optional(),
40499
+ senderId: string2().optional(),
40500
+ work: workItemUpdateSchema
40501
+ }),
40502
+ outputSchema: workUpdateResultSchema,
40503
+ annotations: {
40504
+ readOnlyHint: false,
40505
+ idempotentHint: false,
40506
+ destructiveHint: false,
40507
+ openWorldHint: false
40508
+ }
40509
+ }, async ({ currentDirectory, senderId, work }) => {
40510
+ const resolvedCurrentDirectory = resolveToolCurrentDirectory(currentDirectory, options.defaultCurrentDirectory);
40511
+ const resolvedSenderId = await deps.resolveSenderId(senderId, resolvedCurrentDirectory, env);
40512
+ const workItem = await deps.updateWorkItem({
40513
+ ...work,
40514
+ actorId: resolvedSenderId,
40515
+ source: "scout-mcp"
40516
+ });
40517
+ const structuredContent = {
40518
+ currentDirectory: resolvedCurrentDirectory,
40519
+ senderId: resolvedSenderId,
40520
+ usedBroker: workItem !== null,
40521
+ workItem,
40522
+ workId: workItem?.id ?? null,
40523
+ workUrl: workItem ? `/api/work/${encodeURIComponent(workItem.id)}` : null
40524
+ };
40525
+ return {
40526
+ content: createTextContent(structuredContent),
40527
+ structuredContent
40528
+ };
40529
+ });
40065
40530
  return server;
40066
40531
  }
40067
40532
  async function runScoutMcpServer(options) {
@@ -40072,7 +40537,7 @@ async function runScoutMcpServer(options) {
40072
40537
  const transport = new StdioServerTransport;
40073
40538
  await server.connect(transport);
40074
40539
  }
40075
- var AGENT_STATE_VALUES, REGISTRATION_KIND_VALUES, RESOLVE_KIND_VALUES, flightSchema, agentCandidateSchema, whoAmISchema, searchResultSchema, resolveResultSchema, sendResultSchema, askResultSchema;
40540
+ var AGENT_STATE_VALUES, REGISTRATION_KIND_VALUES, RESOLVE_KIND_VALUES, flightSchema, trackedWorkItemSchema, workItemInputSchema, waitingOnSchema, progressSchema, workItemUpdateSchema, agentCandidateSchema, whoAmISchema, searchResultSchema, resolveResultSchema, sendResultSchema, askResultSchema, workUpdateResultSchema;
40076
40541
  var init_scout_mcp = __esm(async () => {
40077
40542
  init_mcp();
40078
40543
  init_stdio2();
@@ -40081,8 +40546,18 @@ var init_scout_mcp = __esm(async () => {
40081
40546
  init_v4();
40082
40547
  init_product();
40083
40548
  await init_service();
40084
- AGENT_STATE_VALUES = ["offline", "idle", "active", "waiting", "discovered"];
40085
- REGISTRATION_KIND_VALUES = ["broker", "configured", "discovered"];
40549
+ AGENT_STATE_VALUES = [
40550
+ "offline",
40551
+ "idle",
40552
+ "active",
40553
+ "waiting",
40554
+ "discovered"
40555
+ ];
40556
+ REGISTRATION_KIND_VALUES = [
40557
+ "broker",
40558
+ "configured",
40559
+ "discovered"
40560
+ ];
40086
40561
  RESOLVE_KIND_VALUES = ["resolved", "ambiguous", "unresolved"];
40087
40562
  flightSchema = object2({
40088
40563
  id: string2(),
@@ -40097,6 +40572,61 @@ var init_scout_mcp = __esm(async () => {
40097
40572
  completedAt: number2().optional(),
40098
40573
  metadata: record(string2(), unknown()).optional()
40099
40574
  });
40575
+ trackedWorkItemSchema = object2({
40576
+ id: string2(),
40577
+ title: string2(),
40578
+ summary: string2().nullable(),
40579
+ state: _enum2(["open", "working", "waiting", "review", "done", "cancelled"]),
40580
+ acceptanceState: _enum2(["none", "pending", "accepted", "reopened"]),
40581
+ ownerId: string2().nullable(),
40582
+ nextMoveOwnerId: string2().nullable(),
40583
+ conversationId: string2().nullable(),
40584
+ priority: _enum2(["low", "normal", "high", "urgent"]).nullable()
40585
+ });
40586
+ workItemInputSchema = object2({
40587
+ title: string2().min(1),
40588
+ summary: string2().optional(),
40589
+ priority: _enum2(["low", "normal", "high", "urgent"]).optional(),
40590
+ labels: array(string2()).optional(),
40591
+ parentId: string2().optional(),
40592
+ acceptanceState: _enum2(["none", "pending", "accepted", "reopened"]).optional(),
40593
+ metadata: record(string2(), unknown()).optional()
40594
+ });
40595
+ waitingOnSchema = object2({
40596
+ kind: _enum2([
40597
+ "actor",
40598
+ "question",
40599
+ "work_item",
40600
+ "approval",
40601
+ "artifact",
40602
+ "condition"
40603
+ ]),
40604
+ label: string2().min(1),
40605
+ targetId: string2().optional(),
40606
+ metadata: record(string2(), unknown()).optional()
40607
+ });
40608
+ progressSchema = object2({
40609
+ completedSteps: number2().optional(),
40610
+ totalSteps: number2().optional(),
40611
+ checkpoint: string2().optional(),
40612
+ summary: string2().optional(),
40613
+ percent: number2().optional()
40614
+ });
40615
+ workItemUpdateSchema = object2({
40616
+ workId: string2().min(1),
40617
+ title: string2().optional(),
40618
+ summary: string2().nullable().optional(),
40619
+ state: _enum2(["open", "working", "waiting", "review", "done", "cancelled"]).optional(),
40620
+ acceptanceState: _enum2(["none", "pending", "accepted", "reopened"]).optional(),
40621
+ ownerId: string2().nullable().optional(),
40622
+ nextMoveOwnerId: string2().nullable().optional(),
40623
+ priority: _enum2(["low", "normal", "high", "urgent"]).nullable().optional(),
40624
+ labels: array(string2()).optional(),
40625
+ waitingOn: waitingOnSchema.nullable().optional(),
40626
+ progress: progressSchema.nullable().optional(),
40627
+ metadata: record(string2(), unknown()).optional(),
40628
+ eventSummary: string2().optional()
40629
+ });
40100
40630
  agentCandidateSchema = object2({
40101
40631
  agentId: string2(),
40102
40632
  label: string2(),
@@ -40151,11 +40681,23 @@ var init_scout_mcp = __esm(async () => {
40151
40681
  conversationId: string2().nullable(),
40152
40682
  messageId: string2().nullable(),
40153
40683
  flight: flightSchema.nullable(),
40684
+ flightId: string2().nullable(),
40154
40685
  output: string2().nullable(),
40155
40686
  unresolvedTargetId: string2().nullable(),
40156
40687
  unresolvedTargetLabel: string2().nullable(),
40688
+ workItem: trackedWorkItemSchema.nullable(),
40689
+ workId: string2().nullable(),
40690
+ workUrl: string2().nullable(),
40157
40691
  targetDiagnostic: object2({}).catchall(unknown()).nullable()
40158
40692
  });
40693
+ workUpdateResultSchema = object2({
40694
+ currentDirectory: string2(),
40695
+ senderId: string2(),
40696
+ usedBroker: boolean2(),
40697
+ workItem: trackedWorkItemSchema.nullable(),
40698
+ workId: string2().nullable(),
40699
+ workUrl: string2().nullable()
40700
+ });
40159
40701
  });
40160
40702
 
40161
40703
  // ../../apps/desktop/src/cli/commands/mcp.ts
@@ -55989,46 +56531,30 @@ import { dirname as dirname12, join as join26, resolve as resolve10 } from "path
55989
56531
  import { fileURLToPath as fileURLToPath8 } from "url";
55990
56532
  function renderServerCommandHelp() {
55991
56533
  return [
55992
- "scout server \u2014 desktop web UI (Bun runtime)",
56534
+ "scout server \u2014 Scout web UI (Bun runtime)",
55993
56535
  "",
55994
56536
  "Usage:",
55995
56537
  " scout server start [options]",
55996
56538
  " scout server open [options]",
55997
- " scout server control-plane start [options]",
55998
- " scout server control-plane open [options]",
55999
56539
  "",
56000
56540
  "Subcommands:",
56001
- " start Full desktop web API + UI assets (default stack).",
56002
- " open Open the full web UI and start it on demand if needed.",
56003
- " control-plane start Pairing + relay/shell activity only (`@openscout/web` surface).",
56004
- " control-plane open Open the control-plane UI and start it on demand if needed.",
56541
+ " start Start the Scout web UI server.",
56542
+ " open Open the Scout web UI (starts server on demand if needed).",
56005
56543
  "",
56006
56544
  "Options:",
56007
- " --port <n> Listen port (default 3200; env SCOUT_WEB_PORT)",
56008
- " --static Serve built UI from disk (sets SCOUT_STATIC=1)",
56009
- " --static-root DIR Static client root (env SCOUT_STATIC_ROOT)",
56010
- " --vite-url URL Dev proxy target for non-API routes (env SCOUT_VITE_URL)",
56545
+ " --port <n> Listen port (default 3200; env OPENSCOUT_WEB_PORT)",
56546
+ " --static Serve built UI from disk",
56547
+ " --static-root DIR Static client root (env OPENSCOUT_WEB_STATIC_ROOT)",
56548
+ " --vite-url URL Dev proxy target for non-API routes (env OPENSCOUT_WEB_VITE_URL)",
56011
56549
  " --cwd DIR Workspace / setup root (env OPENSCOUT_SETUP_CWD)",
56012
56550
  " --path PATH Browser path for `open` (default /)",
56013
56551
  "",
56014
- "Requires `bun` on PATH.",
56015
- "Published installs include dist/client for the full web UI and dist/control-plane-client",
56016
- "for the minimal control-plane UI; if present and you do not pass --vite-url, the matching",
56017
- "static assets are used by default."
56552
+ "Requires `bun` on PATH."
56018
56553
  ].join(`
56019
56554
  `);
56020
56555
  }
56021
56556
  function resolveScoutWebServerEntry() {
56022
- const mainDir = dirname12(fileURLToPath8(import.meta.url));
56023
- const bundled = join26(mainDir, "scout-web-server.mjs");
56024
- if (existsSync18(bundled)) {
56025
- return bundled;
56026
- }
56027
- const source = fileURLToPath8(new URL("../../server/index.ts", import.meta.url));
56028
- if (existsSync18(source)) {
56029
- return source;
56030
- }
56031
- throw new ScoutCliError("Could not find Scout web server entry. Rebuild @openscout/scout or run from the OpenScout repository.");
56557
+ return resolveScoutControlPlaneWebServerEntry();
56032
56558
  }
56033
56559
  function resolveScoutControlPlaneWebServerEntry() {
56034
56560
  const mainDir = dirname12(fileURLToPath8(import.meta.url));
@@ -56051,25 +56577,25 @@ function parseServerFlags(args) {
56051
56577
  const v = args[++i];
56052
56578
  if (!v)
56053
56579
  throw new ScoutCliError("--port requires a value");
56054
- env.SCOUT_WEB_PORT = v;
56580
+ env.OPENSCOUT_WEB_PORT = v;
56055
56581
  continue;
56056
56582
  }
56057
56583
  if (a === "--static") {
56058
- env.SCOUT_STATIC = "1";
56584
+ env.NODE_ENV = "production";
56059
56585
  continue;
56060
56586
  }
56061
56587
  if (a === "--static-root") {
56062
56588
  const v = args[++i];
56063
56589
  if (!v)
56064
56590
  throw new ScoutCliError("--static-root requires a value");
56065
- env.SCOUT_STATIC_ROOT = v;
56591
+ env.OPENSCOUT_WEB_STATIC_ROOT = v;
56066
56592
  continue;
56067
56593
  }
56068
56594
  if (a === "--vite-url") {
56069
56595
  const v = args[++i];
56070
56596
  if (!v)
56071
56597
  throw new ScoutCliError("--vite-url requires a value");
56072
- env.SCOUT_VITE_URL = v;
56598
+ env.OPENSCOUT_WEB_VITE_URL = v;
56073
56599
  continue;
56074
56600
  }
56075
56601
  if (a === "--cwd") {
@@ -56087,15 +56613,15 @@ function parseServerFlags(args) {
56087
56613
  continue;
56088
56614
  }
56089
56615
  if (a.startsWith("--port=")) {
56090
- env.SCOUT_WEB_PORT = a.slice("--port=".length);
56616
+ env.OPENSCOUT_WEB_PORT = a.slice("--port=".length);
56091
56617
  continue;
56092
56618
  }
56093
56619
  if (a.startsWith("--static-root=")) {
56094
- env.SCOUT_STATIC_ROOT = a.slice("--static-root=".length);
56620
+ env.OPENSCOUT_WEB_STATIC_ROOT = a.slice("--static-root=".length);
56095
56621
  continue;
56096
56622
  }
56097
56623
  if (a.startsWith("--vite-url=")) {
56098
- env.SCOUT_VITE_URL = a.slice("--vite-url=".length);
56624
+ env.OPENSCOUT_WEB_VITE_URL = a.slice("--vite-url=".length);
56099
56625
  continue;
56100
56626
  }
56101
56627
  if (a.startsWith("--cwd=")) {
@@ -56110,9 +56636,9 @@ function parseServerFlags(args) {
56110
56636
  }
56111
56637
  return { env, openPath };
56112
56638
  }
56113
- function resolveBundledStaticClientRoot(entry, mode) {
56639
+ function resolveBundledStaticClientRoot(entry, _mode) {
56114
56640
  const entryDir = dirname12(entry);
56115
- const clientDirectory = mode === "control-plane" ? join26(entryDir, "control-plane-client") : join26(entryDir, "client");
56641
+ const clientDirectory = join26(entryDir, "client");
56116
56642
  const indexPath = join26(clientDirectory, "index.html");
56117
56643
  return existsSync18(indexPath) ? clientDirectory : null;
56118
56644
  }
@@ -56120,12 +56646,18 @@ function buildMergedServerEnv(entry, mode, flagEnv) {
56120
56646
  const bundledStaticClientRoot = resolveBundledStaticClientRoot(entry, mode);
56121
56647
  const autoEnv = {};
56122
56648
  if (bundledStaticClientRoot) {
56123
- const wantsVite = Boolean(flagEnv.SCOUT_VITE_URL ?? process.env.SCOUT_VITE_URL);
56649
+ const wantsVite = Boolean(flagEnv.OPENSCOUT_WEB_VITE_URL ?? process.env.OPENSCOUT_WEB_VITE_URL);
56124
56650
  if (!wantsVite) {
56125
- autoEnv.SCOUT_STATIC = "1";
56126
- autoEnv.SCOUT_STATIC_ROOT = bundledStaticClientRoot;
56651
+ autoEnv.NODE_ENV = "production";
56652
+ autoEnv.OPENSCOUT_WEB_STATIC_ROOT = bundledStaticClientRoot;
56127
56653
  }
56128
56654
  }
56655
+ if (flagEnv.SCOUT_WEB_PORT) {
56656
+ autoEnv.OPENSCOUT_WEB_PORT = flagEnv.SCOUT_WEB_PORT;
56657
+ }
56658
+ if (flagEnv.OPENSCOUT_SETUP_CWD) {
56659
+ autoEnv.OPENSCOUT_SETUP_CWD = flagEnv.OPENSCOUT_SETUP_CWD;
56660
+ }
56129
56661
  return { ...process.env, ...autoEnv, ...flagEnv };
56130
56662
  }
56131
56663
  function parseServerSelection(args) {
@@ -56133,7 +56665,7 @@ function parseServerSelection(args) {
56133
56665
  return {
56134
56666
  action: "start",
56135
56667
  flagArgs: args.slice(1),
56136
- entry: resolveScoutWebServerEntry(),
56668
+ entry: resolveScoutControlPlaneWebServerEntry(),
56137
56669
  mode: "full"
56138
56670
  };
56139
56671
  }
@@ -56141,16 +56673,14 @@ function parseServerSelection(args) {
56141
56673
  return {
56142
56674
  action: "open",
56143
56675
  flagArgs: args.slice(1),
56144
- entry: resolveScoutWebServerEntry(),
56676
+ entry: resolveScoutControlPlaneWebServerEntry(),
56145
56677
  mode: "full"
56146
56678
  };
56147
56679
  }
56148
56680
  if (args[0] === "control-plane") {
56149
- if (args[1] !== "start" && args[1] !== "open") {
56150
- throw new ScoutCliError("expected: scout server control-plane <start|open>");
56151
- }
56681
+ const sub = args[1] === "start" || args[1] === "open" ? args[1] : "start";
56152
56682
  return {
56153
- action: args[1],
56683
+ action: sub,
56154
56684
  flagArgs: args.slice(2),
56155
56685
  entry: resolveScoutControlPlaneWebServerEntry(),
56156
56686
  mode: "control-plane"
@@ -56172,7 +56702,7 @@ function normalizeServerOpenPath(value) {
56172
56702
  return `/${trimmed}`;
56173
56703
  }
56174
56704
  function resolveServerPort(env) {
56175
- const envValue = env.SCOUT_WEB_PORT?.trim();
56705
+ const envValue = (env.OPENSCOUT_WEB_PORT ?? env.SCOUT_WEB_PORT)?.trim();
56176
56706
  if (envValue) {
56177
56707
  const port = Number.parseInt(envValue, 10);
56178
56708
  if (!Number.isFinite(port) || port <= 0) {
@@ -118141,11 +118671,7 @@ function renderScoutHelp(version2 = "0.2.18") {
118141
118671
  "",
118142
118672
  "Commands:",
118143
118673
  commandLines,
118144
- ...deprecatedLines ? [
118145
- "",
118146
- "Deprecated aliases:",
118147
- deprecatedLines
118148
- ] : [],
118674
+ ...deprecatedLines ? ["", "Deprecated aliases:", deprecatedLines] : [],
118149
118675
  "",
118150
118676
  "Global flags:",
118151
118677
  ' --json Structured JSON (doctor: NDJSON stream; last object has phase "complete")',
@@ -118162,6 +118688,10 @@ function renderScoutHelp(version2 = "0.2.18") {
118162
118688
  " scout menu",
118163
118689
  " scout server open",
118164
118690
  "",
118691
+ "One-to-one delegation:",
118692
+ ' scout ask --to hudson "review the parser" # DM by default',
118693
+ ' scout ask --as premotion.master.mini --to hudson "build the editor"',
118694
+ "",
118165
118695
  "Addressing:",
118166
118696
  " @name short form; requires exactly one live match",
118167
118697
  " @name.harness:<codex|claude|...> pin a specific harness (alias: runtime:)",