agent-transport-system 0.7.5 → 0.7.7

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/ats.js CHANGED
@@ -27,7 +27,7 @@ import wrapAnsi from "wrap-ansi";
27
27
  import { Box, Container, Editor, Key, ProcessTerminal, TUI, Text, getEditorKeybindings, matchesKey } from "@mariozechner/pi-tui";
28
28
 
29
29
  //#region package.json
30
- var version = "0.7.5";
30
+ var version = "0.7.7";
31
31
  var package_default = {
32
32
  $schema: "https://www.schemastore.org/package.json",
33
33
  name: "agent-transport-system",
@@ -2510,6 +2510,14 @@ const SPACE_ADD_MEMBERS_PROGRESS_PHASES = [
2510
2510
  }
2511
2511
  ];
2512
2512
  const SPACE_ADD_MEMBERS_PROGRESS_OVERVIEW_STAGES = SPACE_ADD_MEMBERS_PROGRESS_PHASES.map((phase) => `${phase.stage}/${phase.phase}`);
2513
+ const SPACE_ADD_MEMBERS_AGENT_OVERVIEW_STAGES = [
2514
+ "check_arguments",
2515
+ "authenticate",
2516
+ "check_profile",
2517
+ "resolve_target",
2518
+ "add_members/write_membership",
2519
+ "record_join_notices/write_join_notices"
2520
+ ];
2513
2521
  function resolveSpaceAddMembersProgressPhase(input) {
2514
2522
  const contract = SPACE_ADD_MEMBERS_PROGRESS_PHASES.find((phase) => phase.stage === input.stage && phase.phase === input.phase);
2515
2523
  if (!contract) throw new Error(`unknown space add-members progress phase: ${input.stage}/${input.phase}`);
@@ -3273,7 +3281,7 @@ const COMMAND_ENTRY_CONTRACTS = {
3273
3281
  },
3274
3282
  notes: ["space is single-select; members support one or many selections.", "already-joined profiles are skipped automatically."],
3275
3283
  pattern: getSpaceMemberSelectionPatternContract("add-members"),
3276
- stages: SPACE_ADD_MEMBERS_PROGRESS_OVERVIEW_STAGES,
3284
+ stages: [...SPACE_ADD_MEMBERS_AGENT_OVERVIEW_STAGES],
3277
3285
  summary: "Use `ats space add-members --profile <profile-id> <space-id> --member <profile-id...> --view agent` with explicit acting profile, Space ID, and member selection."
3278
3286
  },
3279
3287
  buildHints: (context) => getSpaceMemberSelectionPatternContract("add-members").buildHints?.({
@@ -3461,13 +3469,13 @@ const COMMAND_CHECK_REQUIREMENTS = Object.freeze({
3461
3469
  "service.reinstall": buildCommandChecks(REQUIRED_DISCLAIMER, OPTIONAL_CLI_UPDATE),
3462
3470
  "service.stop": buildCommandChecks(REQUIRED_DISCLAIMER, OPTIONAL_CLI_UPDATE),
3463
3471
  "space.menu": buildCommandChecks(REQUIRED_DISCLAIMER, OPTIONAL_CLI_UPDATE, AUTO_FIX_LOCAL_RUNTIME, REQUIRED_SIGN_IN, CONFIRM_SELECTED_PROFILE),
3464
- "space.create": buildCommandChecks(REQUIRED_DISCLAIMER, OPTIONAL_CLI_UPDATE, AUTO_FIX_LOCAL_RUNTIME, REQUIRED_SIGN_IN, CONFIRM_SELECTED_PROFILE),
3472
+ "space.create": buildCommandChecks(REQUIRED_DISCLAIMER, OPTIONAL_CLI_UPDATE, REQUIRED_SIGN_IN, CONFIRM_SELECTED_PROFILE),
3465
3473
  "space.delete": buildCommandChecks(REQUIRED_DISCLAIMER, OPTIONAL_CLI_UPDATE, AUTO_FIX_LOCAL_RUNTIME, REQUIRED_SIGN_IN, CONFIRM_SELECTED_PROFILE),
3466
3474
  "space.conversation.bind": buildCommandChecks(REQUIRED_DISCLAIMER, OPTIONAL_CLI_UPDATE, AUTO_FIX_LOCAL_RUNTIME, REQUIRED_SIGN_IN, CONFIRM_SELECTED_PROFILE),
3467
3475
  "space.conversation.clear": buildCommandChecks(REQUIRED_DISCLAIMER, OPTIONAL_CLI_UPDATE, AUTO_FIX_LOCAL_RUNTIME, REQUIRED_SIGN_IN, CONFIRM_SELECTED_PROFILE),
3468
3476
  "space.conversation.status": buildCommandChecks(REQUIRED_DISCLAIMER, OPTIONAL_CLI_UPDATE, AUTO_FIX_LOCAL_RUNTIME, REQUIRED_SIGN_IN, CONFIRM_SELECTED_PROFILE),
3469
3477
  "space.join": buildCommandChecks(REQUIRED_DISCLAIMER, OPTIONAL_CLI_UPDATE, AUTO_FIX_LOCAL_RUNTIME, REQUIRED_SIGN_IN, CONFIRM_SELECTED_PROFILE),
3470
- "space.add-members": buildCommandChecks(REQUIRED_DISCLAIMER, OPTIONAL_CLI_UPDATE, AUTO_FIX_LOCAL_RUNTIME, REQUIRED_SIGN_IN, CONFIRM_SELECTED_PROFILE),
3478
+ "space.add-members": buildCommandChecks(REQUIRED_DISCLAIMER, OPTIONAL_CLI_UPDATE, REQUIRED_SIGN_IN, CONFIRM_SELECTED_PROFILE),
3471
3479
  "space.remove-members": buildCommandChecks(REQUIRED_DISCLAIMER, OPTIONAL_CLI_UPDATE, AUTO_FIX_LOCAL_RUNTIME, REQUIRED_SIGN_IN, CONFIRM_SELECTED_PROFILE),
3472
3480
  "space.leave": buildCommandChecks(REQUIRED_DISCLAIMER, OPTIONAL_CLI_UPDATE, AUTO_FIX_LOCAL_RUNTIME, REQUIRED_SIGN_IN, CONFIRM_SELECTED_PROFILE),
3473
3481
  "space.watch": buildCommandChecks(REQUIRED_DISCLAIMER, OPTIONAL_CLI_UPDATE, AUTO_FIX_LOCAL_RUNTIME, REQUIRED_SIGN_IN, CONFIRM_SELECTED_PROFILE),
@@ -28442,13 +28450,21 @@ function showHumanCheckCard(input) {
28442
28450
  //#region src/command-entry-checks/check-cli-update.ts
28443
28451
  const SKIP_CLI_UPDATE_ENV = "ATS_INTERNAL_SKIP_STARTUP_UPGRADE";
28444
28452
  const ATS_PACKAGE_NAME = "agent-transport-system";
28453
+ const OPTIONAL_CLI_UPDATE_CACHE_TTL_MS = 1440 * 60 * 1e3;
28445
28454
  async function runCliUpdateCheck(input) {
28446
28455
  if (input.requirement.mode === "skip") return { status: "continue" };
28447
28456
  if (String(process.env[SKIP_CLI_UPDATE_ENV] ?? "").trim() === "1") return { status: "continue" };
28448
28457
  if (!shouldCheckNpmCliUpdate(input.context)) return { status: "continue" };
28449
28458
  const currentVersion = version;
28450
- const latestVersion = await fetchLatestPackageVersion(ATS_PACKAGE_NAME).catch(() => null);
28451
- if (!(latestVersion && compareSemver(currentVersion, latestVersion) < 0)) return { status: "continue" };
28459
+ const latestVersion = await resolveLatestPackageVersionForUpdateCheck({
28460
+ currentVersion,
28461
+ useLocalCache: input.requirement.mode !== "required"
28462
+ }).catch(() => null);
28463
+ const noUpdateResult = await resolveNoCliUpdateResult({
28464
+ currentVersion,
28465
+ latestVersion
28466
+ });
28467
+ if (noUpdateResult) return noUpdateResult;
28452
28468
  const copy = getCommandEntryCopy(input.context.entryName);
28453
28469
  if (input.context.runtime.resolvedView !== "human" || !input.context.allowPrompt) {
28454
28470
  const isRequired = input.requirement.mode === "required";
@@ -28507,6 +28523,38 @@ async function runCliUpdateCheck(input) {
28507
28523
  })
28508
28524
  };
28509
28525
  }
28526
+ async function resolveNoCliUpdateResult(input) {
28527
+ if (input.latestVersion && compareSemver(input.currentVersion, input.latestVersion) < 0) return null;
28528
+ if (input.latestVersion) await persistLatestVersionCheck({
28529
+ currentVersion: input.currentVersion,
28530
+ latestVersion: input.latestVersion
28531
+ });
28532
+ return { status: "continue" };
28533
+ }
28534
+ async function resolveLatestPackageVersionForUpdateCheck(input) {
28535
+ if (!input.useLocalCache) return await fetchLatestPackageVersion(ATS_PACKAGE_NAME);
28536
+ const previousVersionState = await readVersionState().catch(() => null);
28537
+ const cachedLatestVersion = resolveFreshCachedLatestVersion({
28538
+ currentVersion: input.currentVersion,
28539
+ previousVersionState
28540
+ });
28541
+ if (cachedLatestVersion) return cachedLatestVersion;
28542
+ return await fetchLatestPackageVersion(ATS_PACKAGE_NAME);
28543
+ }
28544
+ async function persistLatestVersionCheck(input) {
28545
+ await writeVersionState(buildNextVersionState({
28546
+ previous: await readVersionState().catch(() => null),
28547
+ currentVersion: input.currentVersion,
28548
+ latestVersion: input.latestVersion
28549
+ })).catch(() => void 0);
28550
+ }
28551
+ function resolveFreshCachedLatestVersion(input) {
28552
+ const state = input.previousVersionState;
28553
+ if (state?.last_version !== input.currentVersion || !state.latest_version || !state.last_checked_at) return null;
28554
+ const checkedAt = Date.parse(state.last_checked_at);
28555
+ if (Number.isNaN(checkedAt) || Date.now() - checkedAt >= OPTIONAL_CLI_UPDATE_CACHE_TTL_MS) return null;
28556
+ return state.latest_version;
28557
+ }
28510
28558
  function shouldCheckNpmCliUpdate(context) {
28511
28559
  return context.environmentTarget.preset === "prod" && context.environmentTarget.userFacingCommand === "ats";
28512
28560
  }
@@ -60440,13 +60488,7 @@ function renderProfileSummaryCard(input) {
60440
60488
  });
60441
60489
  }
60442
60490
  function buildAgentCreateNextSteps(profile) {
60443
- if (profile.profileKind === "agent") return [
60444
- formatAtsCliCommand(`ats setup --profile ${profile.atsProfileId} --local-agent <local-agent-id> --view agent`),
60445
- formatAtsCliCommand(`ats setup --profile ${profile.atsProfileId} --view agent`),
60446
- formatAtsCliCommand(`ats service status --profile ${profile.atsProfileId} --view agent`),
60447
- formatAtsCliCommand(`ats profiles show ${profile.atsProfileId} --view agent`),
60448
- formatAtsCliCommand(`ats whoami --profile ${profile.atsProfileId} --view agent`)
60449
- ];
60491
+ if (profile.profileKind === "agent") return [formatAtsCliCommand(`ats space add-members <space-id> --member ${profile.atsProfileId} --profile <human-profile-id> --view agent`)];
60450
60492
  return [
60451
60493
  formatAtsCliCommand("ats profiles list --view agent"),
60452
60494
  formatAtsCliCommand(`ats profiles set ${profile.atsProfileId} --view agent`),
@@ -60460,28 +60502,24 @@ function buildAgentCreateWakeReadinessData(profile) {
60460
60502
  return {
60461
60503
  identityCreated: true,
60462
60504
  wakeReadinessVerified: false,
60463
- wakeReadinessNote: "This command created the Agent Profile identity. It did not verify that this profile can be woken from a Space or reply from this computer."
60505
+ wakeReadinessNote: "Profile creation creates the Space identity. Add it to a Space when the user wants this teammate to participate."
60464
60506
  };
60465
60507
  }
60466
60508
  function buildProfileCreateWakeReadinessRows(input) {
60467
60509
  if (input.state !== "created" || input.profile.profileKind !== "agent") return [];
60468
60510
  return [{
60469
- label: "Wake availability",
60470
- value: "Not verified by profile creation"
60511
+ label: "Space identity",
60512
+ value: "Created"
60471
60513
  }, {
60472
60514
  label: "Next",
60473
- value: `Run ${formatAtsCliCommand(`ats setup --profile ${input.profile.atsProfileId} --local-agent <local-agent-id>`)} before expecting this Agent Profile to reply from a Space.`
60515
+ value: "Add this profile to a Space when the user wants this teammate to participate."
60474
60516
  }];
60475
60517
  }
60476
60518
  function buildAgentUpdateNextSteps(profile) {
60519
+ if (profile.profileKind === "agent") return [formatAtsCliCommand(`ats profiles show ${profile.atsProfileId} --view agent`), formatAtsCliCommand(`ats space add-members <space-id> --member ${profile.atsProfileId} --profile <human-profile-id> --view agent`)];
60477
60520
  return [
60478
60521
  formatAtsCliCommand(`ats profiles show ${profile.atsProfileId} --view agent`),
60479
60522
  formatAtsCliCommand(`ats profiles update ${profile.atsProfileId} --name <new-name> --view agent`),
60480
- formatAtsCliCommand(`ats setup --profile ${profile.atsProfileId} --local-agent <local-agent-id> --view agent`),
60481
- formatAtsCliCommand(`ats setup --profile ${profile.atsProfileId} --view agent`),
60482
- formatAtsCliCommand(`ats profiles update ${profile.atsProfileId} --workspace-mode ats-managed --view agent`),
60483
- formatAtsCliCommand(`ats profiles update ${profile.atsProfileId} --workspace-mode custom --workspace-path /absolute/path --view agent`),
60484
- formatAtsCliCommand(`ats whoami --profile ${profile.atsProfileId} --view agent`),
60485
60523
  formatAtsCliCommand("ats profiles list --view agent")
60486
60524
  ];
60487
60525
  }
@@ -69476,7 +69514,7 @@ const STAGES_BY_COMMAND = {
69476
69514
  "resolve_target",
69477
69515
  "read_or_update_guide"
69478
69516
  ],
69479
- add_members: SPACE_ADD_MEMBERS_PROGRESS_OVERVIEW_STAGES,
69517
+ add_members: SPACE_ADD_MEMBERS_AGENT_OVERVIEW_STAGES,
69480
69518
  remove_members: [
69481
69519
  "check_arguments",
69482
69520
  "authenticate",
@@ -76043,13 +76081,32 @@ async function resolveSpaceSessionDiagnostics(input) {
76043
76081
  };
76044
76082
  }
76045
76083
  async function emitSpaceCommandPreflight(input) {
76046
- const [authState, replyReadinessSnapshot] = await Promise.all([getAuthSessionState({ validateRemote: false }), resolveCurrentReplyReadinessSnapshot({
76084
+ const actionRequirements = resolveSpacePreflightActionRequirements(input.command);
76085
+ const authState = await getAuthSessionState({ validateRemote: false });
76086
+ if (actionRequirements.localService === "not_required") {
76087
+ const preflight = buildLocalServiceNotRequiredPreflight({
76088
+ actionRequirements,
76089
+ authState,
76090
+ baseUrl: input.baseUrl,
76091
+ command: input.command,
76092
+ profile: input.profile
76093
+ });
76094
+ if (shouldEmitSpaceCommandPreflightOutput(input.emitOutput)) emitResolvedSpaceCommandPreflight({
76095
+ presenter: input.presenter,
76096
+ command: input.command,
76097
+ resolvedView: input.resolvedView,
76098
+ humanServiceGuidanceMode: input.humanServiceGuidanceMode ?? "show",
76099
+ preflight
76100
+ });
76101
+ return preflight;
76102
+ }
76103
+ const replyReadinessSnapshot = await resolveCurrentReplyReadinessSnapshot({
76047
76104
  baseUrl: input.baseUrl,
76048
- checkGatewayChain: input.command === "create" || input.command === "join" || input.command === "send",
76105
+ checkGatewayChain: input.command === "join",
76049
76106
  ownerUserId: input.profile.ownerUserId,
76050
76107
  profile: input.profile,
76051
76108
  runtimeProjection: input.runtimeProjection
76052
- })]);
76109
+ });
76053
76110
  const serviceParticipationReadiness = resolveServiceParticipationReadiness({
76054
76111
  deviceReplyReadiness: replyReadinessSnapshot.deviceReplyReadiness,
76055
76112
  inventory: replyReadinessSnapshot.inventory,
@@ -76075,7 +76132,7 @@ async function emitSpaceCommandPreflight(input) {
76075
76132
  profileName: input.profile.profileName,
76076
76133
  profileKind: input.profile.profileKind
76077
76134
  },
76078
- actionRequirements: resolveSpacePreflightActionRequirements(input.command),
76135
+ actionRequirements,
76079
76136
  agentReplyReadiness: toSpacePreflightAgentReplyReadiness({
76080
76137
  command: input.command,
76081
76138
  readiness: replyReadinessSnapshot.agentReplyReadiness
@@ -76117,6 +76174,62 @@ async function emitSpaceCommandPreflight(input) {
76117
76174
  serviceParticipationReadiness
76118
76175
  };
76119
76176
  }
76177
+ function buildLocalServiceNotRequiredPreflight(input) {
76178
+ const deviceReplyReadiness = {
76179
+ reasonCodes: [],
76180
+ reasonText: input.actionRequirements.localServiceSummary,
76181
+ replyReadiness: "unknown",
76182
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
76183
+ wakeableRouteCount: 0
76184
+ };
76185
+ const serviceParticipationReadiness = {
76186
+ serviceReadiness: "unknown",
76187
+ serviceReadinessState: "unknown",
76188
+ summaryText: "not required",
76189
+ detailText: input.actionRequirements.localServiceSummary,
76190
+ nextStepSummary: null,
76191
+ nextSteps: [],
76192
+ runtimeHeadline: "unknown"
76193
+ };
76194
+ return {
76195
+ deviceReplyReadiness,
76196
+ payload: {
76197
+ command: input.command,
76198
+ auth: {
76199
+ state: input.authState.state,
76200
+ ready: resolvePreflightAuthReadiness({
76201
+ authState: input.authState,
76202
+ baseUrl: input.baseUrl
76203
+ }),
76204
+ compatibleWithBaseUrl: resolvePreflightAuthCompatibility({
76205
+ authState: input.authState,
76206
+ baseUrl: input.baseUrl
76207
+ }),
76208
+ authBaseUrl: input.authState.state === "valid" && input.authState.session ? input.authState.session.authBaseUrl : null,
76209
+ gatewayUrl: input.baseUrl
76210
+ },
76211
+ profile: {
76212
+ profileId: input.profile.atsProfileId,
76213
+ profileName: input.profile.profileName,
76214
+ profileKind: input.profile.profileKind
76215
+ },
76216
+ actionRequirements: input.actionRequirements,
76217
+ agentReplyReadiness: null,
76218
+ services: { daemon: {
76219
+ installed: false,
76220
+ version: null,
76221
+ runtimeStatus: "unknown",
76222
+ runtimeReason: null
76223
+ } },
76224
+ env: {
76225
+ baseUrl: input.baseUrl,
76226
+ requestTimeoutMs: resolveSpaceRequestTimeoutMsForDiagnostics()
76227
+ },
76228
+ serviceRepairGuidance: null
76229
+ },
76230
+ serviceParticipationReadiness
76231
+ };
76232
+ }
76120
76233
  function emitResolvedSpaceCommandPreflight(input) {
76121
76234
  const { payload, serviceParticipationReadiness } = input.preflight;
76122
76235
  if (input.resolvedView === "human") {
@@ -83782,13 +83895,13 @@ function handleBlockedSpaceJoinLocalParticipation(input) {
83782
83895
  if (input.assessmentState === "not_needed") {
83783
83896
  input.presenter.line({
83784
83897
  code: "space.join.service.not_needed",
83785
- text: formatInlineAtsCliCommands("ATS will keep joining this space without local Wake participation on this device. Space membership is separate from whether a local agent can reply from this computer. If you later want local agents from this device to reply, run `ats service status` and follow its recovery guidance.")
83898
+ text: formatInlineAtsCliCommands("ATS will join this space. Local agent participation on this device can be checked later with `ats service status`.")
83786
83899
  });
83787
83900
  return "continue";
83788
83901
  }
83789
83902
  input.presenter.line({
83790
83903
  code: "space.join.service.pending",
83791
- text: formatInlineAtsCliCommands("ATS will keep joining this space without local Wake participation on this device. Space membership is separate from whether a local agent can reply from this computer. Run `ats service status` to inspect local participation before expecting background replies.")
83904
+ text: formatInlineAtsCliCommands("ATS will join this space. Local agent participation on this device can be checked separately with `ats service status`.")
83792
83905
  });
83793
83906
  return "continue";
83794
83907
  }
@@ -83801,10 +83914,10 @@ function buildSpaceJoinMembershipOnlyMessage(input) {
83801
83914
  const profileId = input.atsProfile.atsProfileId;
83802
83915
  const reasonCodes = input.reasonCodes;
83803
83916
  const statusCommand = formatAtsCliCommand(`ats service status --profile ${profileId}`);
83804
- if (reasonCodes.includes("profile.unbound")) return `${profileName} will join this space, but it is not connected to a local agent on this device yet. It can appear here now, but it will not wake or reply from this device until you choose a local agent in ATS Web.`;
83805
- if (reasonCodes.some((reasonCode) => LOCAL_SERVICE_ONLY_JOIN_BLOCK_REASON_CODES.has(reasonCode)) || reasonCodes.includes("dispatch.storage_not_ready") || reasonCodes.includes("service.gateway_chain_unhealthy") || reasonCodes.includes("route.offline") || reasonCodes.includes("route.not_registered")) return formatInlineAtsCliCommands(`${profileName} will join this space, but it will not wake or reply from this device yet. Space membership is separate from local Wake participation. Use \`${statusCommand}\` to check this device; if local participation is unhealthy, follow the status or repair guidance before expecting background replies.`);
83917
+ if (reasonCodes.includes("profile.unbound")) return `${profileName} will join this space. Choose its local agent in ATS Web when you want it to handle work from this device.`;
83918
+ if (reasonCodes.some((reasonCode) => LOCAL_SERVICE_ONLY_JOIN_BLOCK_REASON_CODES.has(reasonCode)) || reasonCodes.includes("dispatch.storage_not_ready") || reasonCodes.includes("service.gateway_chain_unhealthy") || reasonCodes.includes("route.offline") || reasonCodes.includes("route.not_registered")) return formatInlineAtsCliCommands(`${profileName} will join this space. ATS has not confirmed its local reply path on this device yet. Use \`${statusCommand}\` to check this device.`);
83806
83919
  if (reasonCodes.includes("controller.launch.needs_repair") || reasonCodes.includes("controller.launch.choice_required") || reasonCodes.includes("workspace.missing") || reasonCodes.includes("workspace.invalid")) return formatInlineAtsCliCommands(`${profileName} will join this space, but its local agent setup on this device needs attention. Use \`ats agents list\` to find the local agent, then run \`ats agents repair --agent <agent-id>\`.`);
83807
- return `${profileName} will join this space, but local setup on this device is still incomplete. It can appear here now, but it will not wake or reply from this device until you check Local Agents in ATS Web.`;
83920
+ return `${profileName} will join this space. Check Local Agents in ATS Web when you want it to handle work from this device.`;
83808
83921
  }
83809
83922
  function buildJoinTargetMissingMessage(input) {
83810
83923
  return formatMessage(input.resolvedView, "space.target.missing", { command: "join" });
@@ -85054,6 +85167,8 @@ const SPACE_MEMBER_PROFILE_RECONNECT_REASON_CODES = new Set([
85054
85167
  "local_service.identity_mismatch"
85055
85168
  ]);
85056
85169
  const SPACE_MEMBER_SERVICE_STATUS_REASON_CODES = new Set([
85170
+ "agent_profile_binding.local_service_not_connected",
85171
+ "agent_profile_binding.execution_readiness_pending",
85057
85172
  "route.offline",
85058
85173
  "route.not_registered",
85059
85174
  "service.gateway_chain_unhealthy",
@@ -85617,6 +85732,11 @@ function toAuthEndpoint(baseUrl, pathname) {
85617
85732
  function buildSpaceWebUrl(baseUrl, spaceId) {
85618
85733
  const url = new URL(baseUrl);
85619
85734
  if (isLoopbackHostname(url.hostname) && url.port === "8080") url.port = "3000";
85735
+ if (url.hostname === "gateway.ats.sh") {
85736
+ url.hostname = "ats.sh";
85737
+ url.port = "";
85738
+ url.protocol = "https:";
85739
+ }
85620
85740
  url.pathname = `/app/spaces/${encodeURIComponent(spaceId)}`;
85621
85741
  url.search = "";
85622
85742
  url.hash = "";
@@ -86129,7 +86249,7 @@ async function runSpaceAddMembers(input) {
86129
86249
  resolvedView: runtime.resolvedView,
86130
86250
  interactive
86131
86251
  });
86132
- await emitSpaceCommandPreflight({
86252
+ if (shouldRunSpaceAddMembersDiagnosticPreflight(input, explicitMemberIds)) await emitSpaceCommandPreflight({
86133
86253
  presenter,
86134
86254
  command: "add_members",
86135
86255
  profile: atsProfile,
@@ -86321,6 +86441,12 @@ async function runSpaceLeave(input) {
86321
86441
  throw error;
86322
86442
  }
86323
86443
  }
86444
+ function shouldRunSpaceAddMembersDiagnosticPreflight(input, explicitMemberIds) {
86445
+ return input.details === true || input.all === true || explicitMemberIds.length === 0;
86446
+ }
86447
+ function shouldUseFastExplicitSpaceAddMembers(input) {
86448
+ return input.details !== true && input.explicitMemberIds.length > 0;
86449
+ }
86324
86450
  async function runSpaceAddMembersForTarget(input) {
86325
86451
  const targetBaseUrl = input.hasExplicitBaseUrlInput ? input.baseUrl : input.target.baseUrl ?? input.baseUrl;
86326
86452
  const authenticatedGatewayUrl = await ensureSpaceCommandGatewayAuthenticationOrCancel({
@@ -86338,6 +86464,7 @@ async function runSpaceAddMembersForTarget(input) {
86338
86464
  };
86339
86465
  const explicitMemberIds = normalizeRequestedMemberIds(input.explicitMembers);
86340
86466
  const progress = input.details || explicitMemberIds.length === 0 ? addMembersProgress : void 0;
86467
+ const includeLocalParticipation = progress !== void 0 || explicitMemberIds.length === 0;
86341
86468
  const candidates = await resolveSpaceMemberCandidatesForAdd({
86342
86469
  currentProfile: input.atsProfile,
86343
86470
  currentOwnerUserId: input.atsProfile.ownerUserId,
@@ -86345,7 +86472,12 @@ async function runSpaceAddMembersForTarget(input) {
86345
86472
  baseUrl: targetBaseUrl,
86346
86473
  password: input.password,
86347
86474
  explicitMemberIds,
86348
- progress
86475
+ progress,
86476
+ fastExplicitMembers: shouldUseFastExplicitSpaceAddMembers({
86477
+ details: input.details,
86478
+ explicitMemberIds
86479
+ }),
86480
+ includeLocalParticipation
86349
86481
  });
86350
86482
  if (candidates.length === 0 && explicitMemberIds.length === 0) {
86351
86483
  input.presenter.line({
@@ -86377,15 +86509,10 @@ async function runSpaceAddMembersForTarget(input) {
86377
86509
  selectedProfileIds
86378
86510
  });
86379
86511
  if (selectedCandidates.length === 0) return { status: "completed" };
86380
- emitSpaceAddMembersProgressIfRequested(progress, {
86381
- stage: "check_local_wake_readiness",
86382
- phase: "start",
86383
- summary: "Checking whether selected agent profiles can wake from this computer. Members can still be added if local Wake setup needs attention.",
86384
- profileIds: selectedCandidates.map((candidate) => candidate.profileId)
86385
- });
86386
- const servicePreparationResult = await ensureSpaceMemberCandidatesLocalParticipationReady({
86512
+ const servicePreparationResult = await prepareSpaceAddMembersLocalParticipationIfRequested({
86387
86513
  atsProfile: input.atsProfile,
86388
86514
  candidates: selectedCandidates,
86515
+ enabled: includeLocalParticipation,
86389
86516
  progress,
86390
86517
  presenter: input.presenter,
86391
86518
  resolvedView: input.runtime.resolvedView,
@@ -86455,6 +86582,28 @@ async function runSpaceAddMembersForTarget(input) {
86455
86582
  });
86456
86583
  return { status: "completed" };
86457
86584
  }
86585
+ async function prepareSpaceAddMembersLocalParticipationIfRequested(input) {
86586
+ if (!input.enabled) return {
86587
+ status: "continue",
86588
+ candidates: input.candidates
86589
+ };
86590
+ emitSpaceAddMembersProgressIfRequested(input.progress, {
86591
+ stage: "check_local_wake_readiness",
86592
+ phase: "start",
86593
+ summary: "Checking whether selected agent profiles can handle work from this computer. Members can still be added if local setup needs attention.",
86594
+ profileIds: input.candidates.map((candidate) => candidate.profileId)
86595
+ });
86596
+ return await ensureSpaceMemberCandidatesLocalParticipationReady({
86597
+ atsProfile: input.atsProfile,
86598
+ candidates: input.candidates,
86599
+ progress: input.progress,
86600
+ presenter: input.presenter,
86601
+ resolvedView: input.resolvedView,
86602
+ allowPrompt: input.allowPrompt,
86603
+ spaceId: input.spaceId,
86604
+ view: input.view
86605
+ });
86606
+ }
86458
86607
  function emitSpaceAddMembersProgressIfRequested(progress, input) {
86459
86608
  if (!progress) return;
86460
86609
  emitAgentSpaceAddMembersProgress({
@@ -86503,13 +86652,13 @@ function buildSpaceAddMembersLocalWakePlanSummary(plan) {
86503
86652
  if (assessment.profileKind !== "agent") continue;
86504
86653
  counts.set(assessment.localParticipationState, (counts.get(assessment.localParticipationState) ?? 0) + 1);
86505
86654
  }
86506
- return `Local Wake plan: ${[
86507
- formatLocalWakePlanCount(counts.get("ready") ?? 0, "available for local Wake"),
86655
+ return `Local agent plan: ${[
86656
+ formatLocalWakePlanCount(counts.get("ready") ?? 0, "can handle work from this device"),
86508
86657
  formatLocalWakePlanCount(counts.get("needs_agent_prepare") ?? 0, "need agent preparation"),
86509
86658
  formatLocalWakePlanCount(counts.get("needs_ats_service") ?? 0, "need ATS Service"),
86510
86659
  formatLocalWakePlanCount(counts.get("membership_only") ?? 0, "will be added as members only"),
86511
- formatLocalWakePlanCount(counts.get("not_needed") ?? 0, "do not need local Wake setup")
86512
- ].filter((part) => Boolean(part)).join(", ")}. Adding members is separate from making them available for Wake on this computer.`;
86660
+ formatLocalWakePlanCount(counts.get("not_needed") ?? 0, "do not need local agent setup")
86661
+ ].filter((part) => Boolean(part)).join(", ")}. Adding members is separate from local agent participation on this computer.`;
86513
86662
  }
86514
86663
  function formatLocalWakePlanCount(count, label) {
86515
86664
  return count > 0 ? `${String(count)} ${label}` : null;
@@ -86672,7 +86821,7 @@ async function ensureSpaceMemberCandidatesLocalParticipationReady(input) {
86672
86821
  candidates: preparedCandidates.map(toActionParticipationCandidateFromSpaceMemberCandidate)
86673
86822
  }).shouldOfferServiceGate) input.presenter.line({
86674
86823
  code: input.resolvedView === "human" && input.allowPrompt ? "space.add_members.service.declined" : "space.add_members.service.deferred",
86675
- text: formatInlineAtsCliCommands("ATS will continue adding these profiles without local Wake participation on this device. Space membership is separate from whether a local agent can reply from this computer. Run `ats service status` to inspect local participation before expecting background replies.")
86824
+ text: formatInlineAtsCliCommands("ATS will add these profiles to the Space. Local agent participation can be checked separately with `ats service status`.")
86676
86825
  });
86677
86826
  return {
86678
86827
  status: "continue",
@@ -86746,17 +86895,18 @@ function emitSpaceMemberJoinOnlyWarnings(input) {
86746
86895
  }
86747
86896
  function buildSpaceMemberJoinOnlyWarning(candidate) {
86748
86897
  if (candidate.profileKind !== "agent") return null;
86898
+ if (candidate.localParticipationChecked !== true) return null;
86749
86899
  if (isSpaceMemberCandidateBackgroundReplyReady(candidate)) return null;
86750
86900
  const profileLabel = resolveSpaceMemberTerminalProfileLabel(candidate.profileName);
86751
- if (isSpaceMemberCandidateRepairableLocalParticipationCandidate(candidate)) return `${profileLabel} can join this space now, but ${resolveSpaceMemberTerminalLocalTargetLabel({
86901
+ if (isSpaceMemberCandidateRepairableLocalParticipationCandidate(candidate)) return `${profileLabel} can join this space now. ${resolveSpaceMemberTerminalLocalTargetLabel({
86752
86902
  displayName: candidate.localTargetDisplayName,
86753
86903
  agentId: candidate.localTargetAgentId
86754
- })} still needs local setup on this device before it can wake or reply in the background. Use \`${buildSpaceMemberRepairCommand({
86904
+ })} still needs local setup on this device before it can handle work from the Space. Use \`${buildSpaceMemberRepairCommand({
86755
86905
  agentId: candidate.localTargetAgentId,
86756
86906
  profileId: candidate.profileId
86757
- })}\` before expecting background replies.`;
86907
+ })}\` to repair the local agent.`;
86758
86908
  const nextAction = resolveSpaceMemberJoinOnlyNextAction(candidate);
86759
- return `${profileLabel} can join this space now, but it will not wake or reply from this device yet. ${resolveSpaceMemberJoinOnlyReason(candidate)} ${formatSpaceMemberRecoveryNextAction(nextAction)}`;
86909
+ return `${profileLabel} can join this space now. ATS has not confirmed its local reply path on this device yet. ${resolveSpaceMemberJoinOnlyReason(candidate)} ${formatSpaceMemberRecoveryNextAction(nextAction)}`;
86760
86910
  }
86761
86911
  function resolveSpaceMemberJoinOnlyNextAction(candidate) {
86762
86912
  if (candidate.localParticipationReadiness === "not_running") return {
@@ -86834,6 +86984,7 @@ async function refreshSpaceMemberCandidatesLocalReadiness(candidates, progress,
86834
86984
  async function enrichSpaceMemberCandidateLocalParticipationReadiness(candidate, progress, options = {}) {
86835
86985
  if (candidate.profileKind !== "agent" || !candidate.atsProfile || candidate.controllerEnabled !== true || typeof candidate.controllerRef !== "string" || candidate.controllerRef.trim().length === 0) return {
86836
86986
  ...candidate,
86987
+ localParticipationChecked: true,
86837
86988
  localParticipationReadiness: null,
86838
86989
  localParticipationReasonCodes: [],
86839
86990
  localParticipationReasonText: null
@@ -86872,6 +87023,7 @@ async function enrichSpaceMemberCandidateLocalParticipationReadiness(candidate,
86872
87023
  }
86873
87024
  if (!snapshot) return {
86874
87025
  ...candidate,
87026
+ localParticipationChecked: true,
86875
87027
  localParticipationReadiness: null,
86876
87028
  localParticipationReasonCodes: [],
86877
87029
  localParticipationReasonText: null
@@ -86883,6 +87035,7 @@ async function enrichSpaceMemberCandidateLocalParticipationReadiness(candidate,
86883
87035
  });
86884
87036
  return {
86885
87037
  ...candidate,
87038
+ localParticipationChecked: true,
86886
87039
  localParticipationReadiness: readinessSummary.serviceReadiness,
86887
87040
  localParticipationReasonCodes: [...snapshot.deviceReplyReadiness.reasonCodes],
86888
87041
  localParticipationReasonText: snapshot.deviceReplyReadiness.reasonText
@@ -88159,6 +88312,9 @@ function mapSpaceLeaveFailureToGuideError(input) {
88159
88312
  return input.error instanceof Error ? input.error : new Error(String(input.error));
88160
88313
  }
88161
88314
  async function resolveSpaceMemberCandidatesForAdd(input) {
88315
+ const explicitMemberIds = normalizeRequestedMemberIds(input.explicitMemberIds);
88316
+ const includeLocalParticipation = input.includeLocalParticipation !== false;
88317
+ if (input.fastExplicitMembers === true && explicitMemberIds.length > 0) return explicitMemberIds.map(buildFastExplicitSpaceMemberCandidate);
88162
88318
  if (input.progress) emitAgentSpaceAddMembersProgress({
88163
88319
  ...input.progress,
88164
88320
  stage: "resolve_candidates",
@@ -88166,23 +88322,19 @@ async function resolveSpaceMemberCandidatesForAdd(input) {
88166
88322
  summary: "Reading active local profile identities for this Space."
88167
88323
  });
88168
88324
  const profiles = await listAtsProfiles();
88169
- if (input.progress) emitAgentSpaceAddMembersProgress({
88325
+ if (input.progress && includeLocalParticipation) emitAgentSpaceAddMembersProgress({
88170
88326
  ...input.progress,
88171
88327
  stage: "resolve_candidates",
88172
88328
  phase: "read_local_targets",
88173
88329
  summary: "Reading local agent controller state for candidate profiles before selection."
88174
88330
  });
88175
- const localTargetStates = input.progress ? await runSpaceAddMembersProgressHeartbeat({
88176
- ...input.progress,
88177
- stage: "resolve_candidates",
88178
- phase: "read_local_targets_wait",
88179
- summary: "Still reading local agent controller state for candidate profiles before selection.",
88180
- operation: async () => await listAgentTargetStates().catch(() => [])
88181
- }) : await listAgentTargetStates().catch(() => []);
88331
+ const localTargetStates = await listSpaceAddMembersLocalTargetStatesIfRequested({
88332
+ includeLocalParticipation,
88333
+ progress: input.progress
88334
+ });
88182
88335
  const localTargetStateById = new Map(localTargetStates.map((state) => [state.agentId, state]));
88183
88336
  const ownerProfileNameByOwnerUserId = buildOwnerProfileNameByOwnerUserId(profiles);
88184
88337
  const candidateProfiles = profiles.filter((profile) => profile.status === "active" && isSpaceMembershipProfileKind(profile.profileKind) && profile.atsProfileId !== input.currentProfile.atsProfileId).filter((profile) => {
88185
- const explicitMemberIds = input.explicitMemberIds ?? [];
88186
88338
  if (explicitMemberIds.length > 0 && !explicitMemberIds.includes(profile.atsProfileId)) return false;
88187
88339
  return typeof input.currentOwnerUserId !== "string" || input.currentOwnerUserId.trim().length === 0 || profile.ownerUserId === input.currentOwnerUserId;
88188
88340
  });
@@ -88199,29 +88351,58 @@ async function resolveSpaceMemberCandidatesForAdd(input) {
88199
88351
  ...input.password === void 0 ? {} : { spacePassword: input.password }
88200
88352
  });
88201
88353
  const memberProfileIds = new Set([...membersSnapshot.humans, ...membersSnapshot.agents].map((member) => member.profileId));
88202
- return await refreshSpaceMemberCandidatesLocalReadiness((await Promise.all(candidateProfiles.map((profile) => buildSpaceMemberCandidateFromProfile({
88354
+ const candidates = (await Promise.all(candidateProfiles.map((profile) => buildSpaceMemberCandidateFromProfile({
88203
88355
  baseUrl: input.baseUrl,
88204
88356
  profile,
88205
88357
  localTargetStateById,
88206
88358
  ownerProfileName: ownerProfileNameByOwnerUserId.get(profile.ownerUserId) ?? void 0,
88207
88359
  alreadyJoined: memberProfileIds.has(profile.atsProfileId),
88208
- progress: input.progress
88360
+ progress: input.progress,
88361
+ includeLocalParticipation
88209
88362
  })))).sort((left, right) => {
88210
88363
  const byName = left.profileName.localeCompare(right.profileName);
88211
88364
  if (byName !== 0) return byName;
88212
88365
  return left.profileId.localeCompare(right.profileId);
88213
- }), input.progress, { stage: "resolve_candidates" });
88366
+ });
88367
+ if (!includeLocalParticipation) return candidates;
88368
+ return await refreshSpaceMemberCandidatesLocalReadiness(candidates, input.progress, { stage: "resolve_candidates" });
88214
88369
  }
88215
- async function buildSpaceMemberCandidateFromProfile(input) {
88216
- if (input.progress) emitAgentSpaceAddMembersProgress({
88370
+ function buildFastExplicitSpaceMemberCandidate(profileId) {
88371
+ return {
88372
+ profileId,
88373
+ profileName: profileId,
88374
+ profileKind: profileId.startsWith("agt_") ? "agent" : "human",
88375
+ targetMentionLabel: null,
88376
+ localTargetAgentId: null,
88377
+ localTargetDisplayName: null,
88378
+ localTargetLaunchStatus: null,
88379
+ localTargetSelectable: false,
88380
+ localParticipationReadiness: null,
88381
+ localParticipationChecked: false,
88382
+ localParticipationReasonCodes: [],
88383
+ localParticipationReasonText: null,
88384
+ alreadyJoined: false,
88385
+ needsActivation: false
88386
+ };
88387
+ }
88388
+ async function listSpaceAddMembersLocalTargetStatesIfRequested(input) {
88389
+ if (!input.includeLocalParticipation) return [];
88390
+ if (!input.progress) return await listAgentTargetStates().catch(() => []);
88391
+ return await runSpaceAddMembersProgressHeartbeat({
88217
88392
  ...input.progress,
88218
88393
  stage: "resolve_candidates",
88219
- phase: "read_runtime_capability",
88220
- summary: `Reading runtime capability projection for ${resolveSpaceMemberTerminalProfileLabel(input.profile.profileName)}.`,
88221
- profileId: input.profile.atsProfileId,
88222
- profileIds: [input.profile.atsProfileId]
88394
+ phase: "read_local_targets_wait",
88395
+ summary: "Still reading local agent controller state for candidate profiles before selection.",
88396
+ operation: async () => await listAgentTargetStates().catch(() => [])
88223
88397
  });
88224
- const runtimeCapability = input.progress ? await runSpaceAddMembersProgressHeartbeat({
88398
+ }
88399
+ async function resolveSpaceMemberCandidateRuntimeCapabilityIfRequested(input) {
88400
+ if (!input.includeLocalParticipation) return null;
88401
+ if (!input.progress) return await resolveAgentProfilePrimaryRuntimeCapability({
88402
+ baseUrl: input.baseUrl,
88403
+ profile: input.profile
88404
+ }).catch(() => null);
88405
+ return await runSpaceAddMembersProgressHeartbeat({
88225
88406
  ...input.progress,
88226
88407
  stage: "resolve_candidates",
88227
88408
  phase: "read_runtime_capability_wait",
@@ -88232,10 +88413,24 @@ async function buildSpaceMemberCandidateFromProfile(input) {
88232
88413
  baseUrl: input.baseUrl,
88233
88414
  profile: input.profile
88234
88415
  }).catch(() => null)
88235
- }) : await resolveAgentProfilePrimaryRuntimeCapability({
88416
+ });
88417
+ }
88418
+ async function buildSpaceMemberCandidateFromProfile(input) {
88419
+ const includeLocalParticipation = input.includeLocalParticipation !== false;
88420
+ if (input.progress && includeLocalParticipation) emitAgentSpaceAddMembersProgress({
88421
+ ...input.progress,
88422
+ stage: "resolve_candidates",
88423
+ phase: "read_runtime_capability",
88424
+ summary: `Reading runtime capability projection for ${resolveSpaceMemberTerminalProfileLabel(input.profile.profileName)}.`,
88425
+ profileId: input.profile.atsProfileId,
88426
+ profileIds: [input.profile.atsProfileId]
88427
+ });
88428
+ const runtimeCapability = await resolveSpaceMemberCandidateRuntimeCapabilityIfRequested({
88236
88429
  baseUrl: input.baseUrl,
88237
- profile: input.profile
88238
- }).catch(() => null);
88430
+ includeLocalParticipation,
88431
+ profile: input.profile,
88432
+ progress: input.progress
88433
+ });
88239
88434
  const controllerRef = runtimeCapability?.capabilityRef ?? void 0;
88240
88435
  const controllerEnabled = runtimeCapability?.bindingState === "enabled_primary" && runtimeCapability.routable;
88241
88436
  const localTargetAgentId = resolveSpaceMemberCandidateLocalTargetAgentId({
@@ -88260,6 +88455,7 @@ async function buildSpaceMemberCandidateFromProfile(input) {
88260
88455
  localTargetLaunchStatus: localTargetState?.launchStatus ?? null,
88261
88456
  localTargetSelectable: localTargetState?.selectable ?? false,
88262
88457
  localParticipationReadiness: null,
88458
+ localParticipationChecked: false,
88263
88459
  localParticipationReasonCodes: [],
88264
88460
  localParticipationReasonText: null,
88265
88461
  alreadyJoined: input.alreadyJoined,
@@ -88588,14 +88784,19 @@ async function applySpaceAddMembers(input) {
88588
88784
  }
88589
88785
  const addedProfileIds = new Set(response.addedMemberIds);
88590
88786
  const alreadyMemberProfileIds = new Set(response.alreadyMemberIds);
88787
+ const responseItemByProfileId = new Map(response.items.map((item) => [item.profileId, item]));
88591
88788
  const lastJoinedAt = (/* @__PURE__ */ new Date()).toISOString();
88592
88789
  const spaceName = normalizeOptionalString$1(input.spaceName);
88593
88790
  for (const candidate of selectedCandidates) {
88791
+ const nextCandidate = hydrateSpaceMemberCandidateFromResponseItem({
88792
+ candidate,
88793
+ item: responseItemByProfileId.get(candidate.profileId)
88794
+ });
88594
88795
  if (addedProfileIds.has(candidate.profileId)) {
88595
- result.added.push(candidate);
88796
+ result.added.push(nextCandidate);
88596
88797
  continue;
88597
88798
  }
88598
- if (alreadyMemberProfileIds.has(candidate.profileId)) result.alreadyJoined.push(candidate);
88799
+ if (alreadyMemberProfileIds.has(candidate.profileId)) result.alreadyJoined.push(nextCandidate);
88599
88800
  }
88600
88801
  for (const candidate of result.added) try {
88601
88802
  await upsertProfileSpaceHistory({
@@ -88622,6 +88823,27 @@ async function applySpaceAddMembers(input) {
88622
88823
  }
88623
88824
  return result;
88624
88825
  }
88826
+ function hydrateSpaceMemberCandidateFromResponseItem(input) {
88827
+ if (!input.item) return input.candidate;
88828
+ return {
88829
+ ...input.candidate,
88830
+ profileName: input.item.profileName,
88831
+ profileKind: input.item.profileKind,
88832
+ ownerUserId: normalizeOptionalString$1(input.item.ownerUserId) ?? void 0,
88833
+ ownerName: normalizeOptionalString$1(input.item.ownerName) ?? void 0,
88834
+ targetMentionLabel: resolvePrimaryMentionLabelFromSpaceMemberItem(input.item),
88835
+ ...input.item.profileKind === "agent" ? { controllerRef: normalizeOptionalString$1(input.item.controllerRef) ?? input.candidate.controllerRef } : {}
88836
+ };
88837
+ }
88838
+ function resolvePrimaryMentionLabelFromSpaceMemberItem(item) {
88839
+ const mentionAlias = normalizeOptionalString$1(item.mentionAlias);
88840
+ if (mentionAlias) return mentionAlias;
88841
+ return resolveSingleSpaceMentionLabels({
88842
+ mentionAlias,
88843
+ profileId: item.profileId,
88844
+ profileName: item.profileName
88845
+ }).primaryMentionLabel;
88846
+ }
88625
88847
  async function waitForAddedMembersWakeProjection(input) {
88626
88848
  const expectedWakeableProfileIds = resolveExpectedWakeProjectionProfileIds(input.result);
88627
88849
  if (expectedWakeableProfileIds.length === 0) return;
@@ -88728,6 +88950,7 @@ function emitSpaceAddMembersResult(input) {
88728
88950
  }
88729
88951
  function buildSpaceMemberJoinedFollowUp(candidate) {
88730
88952
  if (candidate.profileKind !== "agent") return null;
88953
+ if (candidate.localParticipationChecked !== true) return null;
88731
88954
  if (isSpaceMemberCandidateRepairableLocalParticipationCandidate(candidate)) {
88732
88955
  const repairCommand = buildSpaceMemberRepairCommand({
88733
88956
  agentId: candidate.localTargetAgentId,
@@ -88741,7 +88964,7 @@ function buildSpaceMemberJoinedFollowUp(candidate) {
88741
88964
  return {
88742
88965
  profileId: candidate.profileId,
88743
88966
  reasonCodes: candidate.localParticipationReasonCodes ?? [],
88744
- text: `${profileLabel} joined this space, but ${agentLabel} still needs repair on this device before it can wake or reply in the background. Use \`${repairCommand}\` before expecting background replies.`
88967
+ text: `${profileLabel} joined this space. ${agentLabel} still needs repair on this device before it can handle work from the Space. Use \`${repairCommand}\` to repair the local agent.`
88745
88968
  };
88746
88969
  }
88747
88970
  if (!isSpaceMemberCandidateRunnableLocalParticipationCandidate(candidate)) {
@@ -88750,7 +88973,7 @@ function buildSpaceMemberJoinedFollowUp(candidate) {
88750
88973
  return {
88751
88974
  profileId: candidate.profileId,
88752
88975
  reasonCodes: candidate.localParticipationReasonCodes ?? [],
88753
- text: `${profileLabel} joined this space, but it is not connected to a local agent on this device yet. It can appear here now, but it will not wake or reply from this device until you choose a local agent. ${formatSpaceMemberRecoveryNextAction(nextAction)}`
88976
+ text: `${profileLabel} joined this space. ATS has not confirmed its local reply path on this device yet. ${formatSpaceMemberRecoveryNextAction(nextAction)}`
88754
88977
  };
88755
88978
  }
88756
88979
  return null;
@@ -88985,8 +89208,8 @@ async function persistSpaceAddMembersJoinNotices(input) {
88985
89208
  failedCount: 0
88986
89209
  };
88987
89210
  const failures = [];
88988
- let targetMentionLabelByProfileId;
88989
- try {
89211
+ let targetMentionLabelByProfileId = buildKnownMentionLabelByProfileId(input.addedMembers);
89212
+ if (!hasMentionLabelsForAllMembers(input.addedMembers, targetMentionLabelByProfileId)) try {
88990
89213
  targetMentionLabelByProfileId = buildSpacePrimaryMentionLabelByProfileId(await createCliSpaceApi(input.baseUrl).getMembersSnapshot({
88991
89214
  spaceId: input.space,
88992
89215
  requestContext: buildAtsRequestContextFromProfile({ atsProfile: input.actorProfile }),
@@ -89032,6 +89255,17 @@ async function persistSpaceAddMembersJoinNotices(input) {
89032
89255
  ...failures[0] ? { firstFailure: toStructuredGatewayFailure(failures[0].error) } : {}
89033
89256
  };
89034
89257
  }
89258
+ function buildKnownMentionLabelByProfileId(members) {
89259
+ const labelsByProfileId = /* @__PURE__ */ new Map();
89260
+ for (const member of members) {
89261
+ const targetMentionLabel = normalizeOptionalString$1(member.targetMentionLabel);
89262
+ if (targetMentionLabel) labelsByProfileId.set(member.profileId, targetMentionLabel);
89263
+ }
89264
+ return labelsByProfileId;
89265
+ }
89266
+ function hasMentionLabelsForAllMembers(members, labelsByProfileId) {
89267
+ return members.every((member) => labelsByProfileId.has(member.profileId));
89268
+ }
89035
89269
  async function postSpaceAddMemberJoinNotice(input) {
89036
89270
  const requestContext = buildAtsRequestContextFromProfile({ atsProfile: input.actorProfile });
89037
89271
  await createCliSpaceApi(input.baseUrl).postNormalMessage({
@@ -89217,8 +89451,9 @@ function resolveSpaceMemberCandidateStatusLabel(candidate) {
89217
89451
  const TRAILING_PERIOD_RE = /\.$/u;
89218
89452
  function resolveSpaceMemberCandidateStatusBadges(candidate) {
89219
89453
  if (candidate.profileKind !== "agent") return [];
89454
+ if (candidate.localParticipationChecked !== true) return [];
89220
89455
  if (isSpaceMemberCandidateBackgroundReplyReady(candidate)) return ["Local setup connected"];
89221
- if (isSpaceMemberCandidateRepairableLocalParticipationCandidate(candidate)) return ["Needs repair before background replies"];
89456
+ if (isSpaceMemberCandidateRepairableLocalParticipationCandidate(candidate)) return ["Needs repair"];
89222
89457
  return [resolveSpaceMemberJoinOnlyReason(candidate).replace(TRAILING_PERIOD_RE, ""), "Joins only for now"];
89223
89458
  }
89224
89459
  function isSpaceMemberCandidateBackgroundReplyReady(candidate) {
@@ -89242,7 +89477,7 @@ function resolveSpaceMemberProfileConnectionAction(candidate) {
89242
89477
  kind: "instruction"
89243
89478
  };
89244
89479
  if (candidate.controllerEnabled !== true || typeof candidate.controllerRef !== "string" || candidate.controllerRef.trim().length === 0 || reasonCodes.some((reasonCode) => SPACE_MEMBER_PROFILE_CONNECTION_REASON_CODES.has(reasonCode))) return {
89245
- instruction: "Open this Agent in ATS Web and choose the local agent that should handle Wake work.",
89480
+ instruction: "Open this Agent in ATS Web and choose the local agent that should handle work from the Space.",
89246
89481
  kind: "instruction"
89247
89482
  };
89248
89483
  if (reasonCodes.includes("controller.binding.disabled")) return {
@@ -89255,9 +89490,9 @@ function hasSpaceMemberReasonCode(candidate, reasonCodes) {
89255
89490
  return (candidate.localParticipationReasonCodes ?? []).some((reasonCode) => reasonCodes.has(reasonCode));
89256
89491
  }
89257
89492
  function formatSpaceMemberRecoveryNextAction(action) {
89258
- if (action.kind === "instruction") return `${action.instruction} Do this before expecting background replies.`;
89259
- if (action.command === "ats agents list") return formatInlineAtsCliCommands("Use `ats agents list` to find the local agent that needs repair before expecting background replies.");
89260
- return `Use \`${formatAtsCliCommand(action.command)}\` before expecting background replies.`;
89493
+ if (action.kind === "instruction") return action.instruction;
89494
+ if (action.command === "ats agents list") return formatInlineAtsCliCommands("Use `ats agents list` to find the local agent that needs repair.");
89495
+ return `Use \`${formatAtsCliCommand(action.command)}\` to check the local reply path.`;
89261
89496
  }
89262
89497
  function resolveSpaceMemberTerminalProfileLabel(profileName) {
89263
89498
  return sanitizeSingleLinePromptText(normalizeOptionalString$1(profileName)) || "This agent";
@@ -100025,8 +100260,8 @@ function isSpaceCommandToken(token) {
100025
100260
  }
100026
100261
  async function resolveEffectiveViewForOutput() {
100027
100262
  const explicitView = parseViewFromArgv(process.argv, { allowMissingValue: true });
100028
- const configuredView = await readConfiguredDefaultView({ argv: process.argv });
100029
- const selectedView = explicitView ?? configuredView;
100263
+ if (explicitView === "human" || explicitView === "agent") return explicitView;
100264
+ const selectedView = await readConfiguredDefaultView({ argv: process.argv });
100030
100265
  if (selectedView === "human" || selectedView === "agent") return selectedView;
100031
100266
  return (await resolveRuntimeContext({ view: "auto" })).resolvedView;
100032
100267
  }