@openscout/scout 0.2.37 → 0.2.40

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.
@@ -1202,27 +1202,38 @@ function agentIdentityMatches(identity, candidate) {
1202
1202
  return true;
1203
1203
  }
1204
1204
  function resolveAgentIdentity(identity, candidates) {
1205
+ const diagnosis = diagnoseAgentIdentity(identity, candidates);
1206
+ return diagnosis.kind === "resolved" ? diagnosis.match : null;
1207
+ }
1208
+ function diagnoseAgentIdentity(identity, candidates) {
1205
1209
  const aliasKeys = identityAliasKeys(identity);
1206
1210
  const exactAliasMatches = candidates.filter((candidate) => {
1207
1211
  const candidateAliasKeys = explicitCandidateAliases(candidate).map(canonicalizeAliasValue);
1208
1212
  return aliasKeys.some((key) => candidateAliasKeys.includes(key));
1209
1213
  });
1210
1214
  if (exactAliasMatches.length === 1) {
1211
- return exactAliasMatches[0];
1215
+ return { kind: "resolved", match: exactAliasMatches[0] };
1212
1216
  }
1213
1217
  if (exactAliasMatches.length > 1) {
1214
- return null;
1218
+ return { kind: "ambiguous", candidates: exactAliasMatches };
1215
1219
  }
1216
1220
  const matches = candidates.filter((candidate) => agentIdentityMatches(identity, candidate));
1217
1221
  if (matches.length === 1) {
1218
- return matches[0];
1222
+ return { kind: "resolved", match: matches[0] };
1223
+ }
1224
+ if (matches.length === 0) {
1225
+ return { kind: "unknown" };
1219
1226
  }
1220
1227
  if (!identity.nodeQualifier && !identity.workspaceQualifier && !identity.profile && !identity.harness) {
1221
- return matches.find((candidate) => normalizeAgentIdentitySegment(candidate.agentId) === identity.definitionId) ?? matches[0] ?? null;
1228
+ const exactIdMatch = matches.find((candidate) => normalizeAgentIdentitySegment(candidate.agentId) === identity.definitionId);
1229
+ if (exactIdMatch) {
1230
+ return { kind: "resolved", match: exactIdMatch };
1231
+ }
1232
+ return { kind: "ambiguous", candidates: matches };
1222
1233
  }
1223
- return null;
1234
+ return { kind: "ambiguous", candidates: matches };
1224
1235
  }
1225
- var DIMENSION_ALIASES, normalizeAgentSelectorSegment, parseAgentSelector, formatAgentSelector, extractAgentSelectors, resolveAgentSelector;
1236
+ var DIMENSION_ALIASES, normalizeAgentSelectorSegment, SCOUT_DISPATCHER_AGENT_ID = "scout", BUILT_IN_AGENT_DEFINITION_IDS, RESERVED_AGENT_DEFINITION_IDS, parseAgentSelector, formatAgentSelector, extractAgentSelectors, resolveAgentSelector;
1226
1237
  var init_agent_identity = __esm(() => {
1227
1238
  DIMENSION_ALIASES = {
1228
1239
  workspace: "workspace",
@@ -1236,6 +1247,15 @@ var init_agent_identity = __esm(() => {
1236
1247
  host: "node"
1237
1248
  };
1238
1249
  normalizeAgentSelectorSegment = normalizeAgentIdentitySegment;
1250
+ BUILT_IN_AGENT_DEFINITION_IDS = new Set([
1251
+ SCOUT_DISPATCHER_AGENT_ID,
1252
+ "builder",
1253
+ "reviewer",
1254
+ "research"
1255
+ ]);
1256
+ RESERVED_AGENT_DEFINITION_IDS = new Set([
1257
+ SCOUT_DISPATCHER_AGENT_ID
1258
+ ]);
1239
1259
  parseAgentSelector = parseAgentIdentity;
1240
1260
  formatAgentSelector = formatAgentIdentity;
1241
1261
  extractAgentSelectors = extractAgentIdentities;
@@ -2975,7 +2995,7 @@ async function readRelayAgentOverrides() {
2975
2995
  return Object.fromEntries(Object.entries(agents).map(([agentId, record]) => {
2976
2996
  const definitionId = normalizeAgentId(record.definitionId || record.agentId || agentId);
2977
2997
  const projectRoot = normalizePath(record.projectRoot);
2978
- const concreteAgentId = BUILT_IN_AGENT_IDS.has(definitionId) ? definitionId : buildRelayAgentInstance(definitionId, projectRoot).id;
2998
+ const concreteAgentId = buildRelayAgentInstance(definitionId, projectRoot).id;
2979
2999
  const defaultHarness = normalizeManagedHarness(typeof record.defaultHarness === "string" ? record.defaultHarness : record.runtime?.harness, "claude");
2980
3000
  const harnessProfiles = buildHarnessProfiles({
2981
3001
  projectRoot,
@@ -3010,7 +3030,7 @@ async function writeRelayAgentOverrides(overrides) {
3010
3030
  const normalizedAgents = Object.fromEntries(Object.entries(overrides).map(([agentId, record]) => {
3011
3031
  const definitionId = normalizeAgentId(record.definitionId || record.agentId || agentId);
3012
3032
  const projectRoot = normalizePath(record.projectRoot);
3013
- const concreteAgentId = BUILT_IN_AGENT_IDS.has(definitionId) ? definitionId : buildRelayAgentInstance(definitionId, projectRoot).id;
3033
+ const concreteAgentId = buildRelayAgentInstance(definitionId, projectRoot).id;
3014
3034
  const defaultHarness = normalizeManagedHarness(typeof record.defaultHarness === "string" ? record.defaultHarness : record.runtime?.harness, "claude");
3015
3035
  const harnessProfiles = buildHarnessProfiles({
3016
3036
  projectRoot,
@@ -3588,14 +3608,14 @@ async function loadResolvedRelayAgents(options = {}) {
3588
3608
  const manifest = await readProjectConfig(projectRoot);
3589
3609
  const override = overrideByRoot.get(projectRoot);
3590
3610
  const resolvedAgent = manifest ? await resolveManifestBackedAgent(projectRoot, manifest, settings, override) : await resolveInferredAgent(projectRoot, settings, override);
3591
- if (!resolvedAgent.agentId || BUILT_IN_AGENT_IDS.has(resolvedAgent.agentId)) {
3611
+ if (!resolvedAgent.agentId || BUILT_IN_AGENT_DEFINITION_IDS.has(resolvedAgent.definitionId)) {
3592
3612
  continue;
3593
3613
  }
3594
3614
  resolvedAgents.push(resolvedAgent);
3595
3615
  }
3596
3616
  const dedupedResolvedAgents = await dedupeResolvedAgentsByCanonicalProjectRoot(resolvedAgents);
3597
3617
  const configuredAgents = dedupedResolvedAgents.filter((agent) => agent.registrationKind === "configured");
3598
- const builtInOverrides = Object.fromEntries(Object.entries(overrides).filter(([agentId]) => BUILT_IN_AGENT_IDS.has(agentId)));
3618
+ const builtInOverrides = Object.fromEntries(Object.entries(overrides).filter(([, record]) => record.definitionId ? BUILT_IN_AGENT_DEFINITION_IDS.has(record.definitionId) : false));
3599
3619
  const nextOverrides = {
3600
3620
  ...builtInOverrides,
3601
3621
  ...Object.fromEntries(configuredAgents.map((agent) => [
@@ -3687,11 +3707,12 @@ async function ensureRelayAgentConfigured(value, options = {}) {
3687
3707
  async function ensureScoutRelayAgentConfigured(options = {}) {
3688
3708
  const settings = await readOpenScoutSettings({ currentDirectory: options.currentDirectory });
3689
3709
  const overrides = await readRelayAgentOverrides();
3690
- const existing = overrides[SCOUT_AGENT_ID];
3691
3710
  const resolvedProjectRoot = options.projectRoot ? normalizePath(options.projectRoot) : options.currentDirectory ? await findNearestProjectRoot(options.currentDirectory) ?? normalizePath(options.currentDirectory) : normalizePath(process.cwd());
3711
+ const qualifiedAgentId = buildRelayAgentInstance(SCOUT_AGENT_ID, resolvedProjectRoot).id;
3712
+ const existing = overrides[qualifiedAgentId] ?? overrides[SCOUT_AGENT_ID];
3692
3713
  const nextOverride = {
3693
3714
  ...existing,
3694
- agentId: SCOUT_AGENT_ID,
3715
+ agentId: qualifiedAgentId,
3695
3716
  definitionId: SCOUT_AGENT_ID,
3696
3717
  displayName: "Scout",
3697
3718
  projectName: "OpenScout",
@@ -3704,7 +3725,7 @@ async function ensureScoutRelayAgentConfigured(options = {}) {
3704
3725
  defaultHarness: "claude",
3705
3726
  harnessProfiles: buildHarnessProfiles({
3706
3727
  projectRoot: resolvedProjectRoot,
3707
- sessionKey: SCOUT_AGENT_ID,
3728
+ sessionKey: qualifiedAgentId,
3708
3729
  sessionPrefix: settings.agents.sessionPrefix,
3709
3730
  defaultHarness: "claude",
3710
3731
  profiles: existing?.harnessProfiles,
@@ -3720,13 +3741,16 @@ async function ensureScoutRelayAgentConfigured(options = {}) {
3720
3741
  }
3721
3742
  };
3722
3743
  nextOverride.launchArgs = nextOverride.harnessProfiles?.claude?.launchArgs ?? [];
3723
- if (JSON.stringify(existing) !== JSON.stringify(nextOverride)) {
3724
- overrides[SCOUT_AGENT_ID] = nextOverride;
3744
+ if (overrides[SCOUT_AGENT_ID]) {
3745
+ delete overrides[SCOUT_AGENT_ID];
3746
+ }
3747
+ if (JSON.stringify(overrides[qualifiedAgentId]) !== JSON.stringify(nextOverride)) {
3748
+ overrides[qualifiedAgentId] = nextOverride;
3725
3749
  await writeRelayAgentOverrides(overrides);
3726
3750
  }
3727
3751
  return nextOverride;
3728
3752
  }
3729
- var SCOUT_AGENT_ID = "scout", SCOUT_PRIMARY_CONVERSATION_ID = "dm.scout.primary", MANAGED_AGENT_HARNESSES, DEFAULT_OPERATOR_NAME, DEFAULT_CAPABILITIES, DEFAULT_TRANSPORT = "claude_stream_json", DEFAULT_TELEGRAM_MODE = "polling", LEGACY_DEFAULT_TELEGRAM_CONVERSATION_ID = "channel.shared", DEFAULT_TELEGRAM_CONVERSATION_ID, SETTINGS_VERSION = 1, PROJECT_CONFIG_VERSION = 1, BUILT_IN_AGENT_IDS, PROJECT_SCAN_SKIP_DIRECTORIES, PROJECT_STRONG_MARKERS, PROJECT_WEAK_MARKERS, PROJECT_HARNESS_MARKERS, PROJECT_STRONG_MARKERS_FLAT_NESTED, PROJECT_WEAK_MARKERS_FLAT_NESTED, GIT_BRANCH_CACHE_TTL_MS = 15000, gitBranchCache, SCOUT_SKILL_FILE_NAME = "SKILL.md", SETUP_MODULE_DIRECTORY, SCOUT_SKILL_REPO_ROOT, SCOUT_SKILL_INSTALL_PATHS, PROJECT_SCAN_MAX_DEPTH = 64;
3753
+ var SCOUT_AGENT_ID = "scout", SCOUT_PRIMARY_CONVERSATION_ID = "dm.scout.primary", MANAGED_AGENT_HARNESSES, DEFAULT_OPERATOR_NAME, DEFAULT_CAPABILITIES, DEFAULT_TRANSPORT = "claude_stream_json", DEFAULT_TELEGRAM_MODE = "polling", LEGACY_DEFAULT_TELEGRAM_CONVERSATION_ID = "channel.shared", DEFAULT_TELEGRAM_CONVERSATION_ID, SETTINGS_VERSION = 1, PROJECT_CONFIG_VERSION = 1, PROJECT_SCAN_SKIP_DIRECTORIES, PROJECT_STRONG_MARKERS, PROJECT_WEAK_MARKERS, PROJECT_HARNESS_MARKERS, PROJECT_STRONG_MARKERS_FLAT_NESTED, PROJECT_WEAK_MARKERS_FLAT_NESTED, GIT_BRANCH_CACHE_TTL_MS = 15000, gitBranchCache, SCOUT_SKILL_FILE_NAME = "SKILL.md", SETUP_MODULE_DIRECTORY, SCOUT_SKILL_REPO_ROOT, SCOUT_SKILL_INSTALL_PATHS, PROJECT_SCAN_MAX_DEPTH = 64;
3730
3754
  var init_setup = __esm(() => {
3731
3755
  init_dist();
3732
3756
  init_src();
@@ -3737,7 +3761,6 @@ var init_setup = __esm(() => {
3737
3761
  DEFAULT_OPERATOR_NAME = guessedOperatorName();
3738
3762
  DEFAULT_CAPABILITIES = ["chat", "invoke", "deliver"];
3739
3763
  DEFAULT_TELEGRAM_CONVERSATION_ID = SCOUT_PRIMARY_CONVERSATION_ID;
3740
- BUILT_IN_AGENT_IDS = new Set(["scout", "builder", "reviewer", "research"]);
3741
3764
  PROJECT_SCAN_SKIP_DIRECTORIES = new Set([
3742
3765
  ".git",
3743
3766
  ".hg",
@@ -4833,6 +4856,24 @@ import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as rea
4833
4856
  import { homedir as homedir5 } from "os";
4834
4857
  import { basename as basename3, dirname as dirname5, join as join8, resolve as resolve3 } from "path";
4835
4858
  import { fileURLToPath as fileURLToPath4 } from "url";
4859
+ function isTmpPath(p) {
4860
+ return /^\/(?:private\/)?tmp\//.test(p);
4861
+ }
4862
+ function resolveAdvertiseScope() {
4863
+ const raw2 = (process.env.OPENSCOUT_ADVERTISE_SCOPE ?? "").trim().toLowerCase();
4864
+ if (raw2 === "mesh")
4865
+ return "mesh";
4866
+ if (raw2 === "local")
4867
+ return "local";
4868
+ return DEFAULT_ADVERTISE_SCOPE;
4869
+ }
4870
+ function resolveBrokerHost(scope = resolveAdvertiseScope()) {
4871
+ const explicit = process.env.OPENSCOUT_BROKER_HOST;
4872
+ if (typeof explicit === "string" && explicit.trim().length > 0) {
4873
+ return explicit;
4874
+ }
4875
+ return scope === "mesh" ? DEFAULT_BROKER_HOST_MESH : DEFAULT_BROKER_HOST;
4876
+ }
4836
4877
  function buildDefaultBrokerUrl(host = DEFAULT_BROKER_HOST, port = DEFAULT_BROKER_PORT) {
4837
4878
  return `http://${host}:${port}`;
4838
4879
  }
@@ -4853,15 +4894,28 @@ function isInstalledRuntimePackageDir(candidate) {
4853
4894
  return existsSync5(join8(candidate, "package.json")) && existsSync5(join8(candidate, "bin", "openscout-runtime.mjs"));
4854
4895
  }
4855
4896
  function findGlobalRuntimeDir() {
4856
- const bunCandidate = join8(homedir5(), ".bun", "node_modules", "@openscout", "runtime");
4857
- if (isInstalledRuntimePackageDir(bunCandidate))
4858
- return bunCandidate;
4859
- const bunGlobalCandidate = join8(homedir5(), ".bun", "install", "global", "node_modules", "@openscout", "runtime");
4860
- if (isInstalledRuntimePackageDir(bunGlobalCandidate))
4861
- return bunGlobalCandidate;
4862
- const bunScoutNested = join8(homedir5(), ".bun", "install", "global", "node_modules", "@openscout", "scout", "node_modules", "@openscout", "runtime");
4863
- if (isInstalledRuntimePackageDir(bunScoutNested))
4864
- return bunScoutNested;
4897
+ const candidates = [
4898
+ join8(homedir5(), ".bun", "node_modules", "@openscout", "runtime"),
4899
+ join8(homedir5(), ".bun", "install", "global", "node_modules", "@openscout", "runtime"),
4900
+ join8(homedir5(), ".bun", "install", "global", "node_modules", "@openscout", "scout", "node_modules", "@openscout", "runtime")
4901
+ ];
4902
+ for (const c of candidates) {
4903
+ if (isInstalledRuntimePackageDir(c))
4904
+ return c;
4905
+ }
4906
+ try {
4907
+ const result = spawnSync("which", ["scout"], { encoding: "utf8", timeout: 3000 });
4908
+ const scoutBin = result.stdout?.trim();
4909
+ if (scoutBin) {
4910
+ const scoutPkg = resolve3(scoutBin, "..", "..");
4911
+ const nested = join8(scoutPkg, "node_modules", "@openscout", "runtime");
4912
+ if (isInstalledRuntimePackageDir(nested))
4913
+ return nested;
4914
+ const sibling = resolve3(scoutPkg, "..", "runtime");
4915
+ if (isInstalledRuntimePackageDir(sibling))
4916
+ return sibling;
4917
+ }
4918
+ } catch {}
4865
4919
  return null;
4866
4920
  }
4867
4921
  function findWorkspaceRuntimeDir(startDir) {
@@ -4935,11 +4989,12 @@ function resolveBrokerServiceConfig() {
4935
4989
  const label = resolveBrokerServiceLabel(mode);
4936
4990
  const uid = typeof process.getuid === "function" ? process.getuid() : Number.parseInt(process.env.UID ?? "0", 10);
4937
4991
  const supportPaths = resolveOpenScoutSupportPaths();
4938
- const supportDirectory = supportPaths.supportDirectory;
4939
- const logsDirectory = supportPaths.brokerLogsDirectory;
4940
- const rawControlHome = supportPaths.controlHome;
4941
- const controlHome = /^\/(?:private\/)?tmp\//.test(rawControlHome) ? join8(homedir5(), ".openscout", "control-plane") : rawControlHome;
4942
- const brokerHost = process.env.OPENSCOUT_BROKER_HOST ?? DEFAULT_BROKER_HOST;
4992
+ const defaultSupportDir = join8(homedir5(), "Library", "Application Support", "OpenScout");
4993
+ const supportDirectory = isTmpPath(supportPaths.supportDirectory) ? defaultSupportDir : supportPaths.supportDirectory;
4994
+ const logsDirectory = join8(supportDirectory, "logs", "broker");
4995
+ const controlHome = isTmpPath(supportPaths.controlHome) ? join8(homedir5(), ".openscout", "control-plane") : supportPaths.controlHome;
4996
+ const advertiseScope = resolveAdvertiseScope();
4997
+ const brokerHost = resolveBrokerHost(advertiseScope);
4943
4998
  const brokerPort = Number.parseInt(process.env.OPENSCOUT_BROKER_PORT ?? String(DEFAULT_BROKER_PORT), 10);
4944
4999
  const brokerUrl = process.env.OPENSCOUT_BROKER_URL ?? buildDefaultBrokerUrl(brokerHost, brokerPort);
4945
5000
  const launchAgentPath = join8(homedir5(), "Library", "LaunchAgents", `${label}.plist`);
@@ -4959,7 +5014,8 @@ function resolveBrokerServiceConfig() {
4959
5014
  bunExecutable: resolveBunExecutable(),
4960
5015
  brokerHost,
4961
5016
  brokerPort,
4962
- brokerUrl
5017
+ brokerUrl,
5018
+ advertiseScope
4963
5019
  };
4964
5020
  }
4965
5021
  function renderLaunchAgentPlist(config) {
@@ -4971,6 +5027,7 @@ function renderLaunchAgentPlist(config) {
4971
5027
  OPENSCOUT_CONTROL_HOME: config.controlHome,
4972
5028
  OPENSCOUT_BROKER_SERVICE_MODE: config.mode,
4973
5029
  OPENSCOUT_BROKER_SERVICE_LABEL: config.label,
5030
+ OPENSCOUT_ADVERTISE_SCOPE: config.advertiseScope,
4974
5031
  HOME: homedir5(),
4975
5032
  PATH: launchPath,
4976
5033
  ...collectOptionalEnvVars([
@@ -5041,7 +5098,7 @@ function resolveLaunchAgentPATH() {
5041
5098
  "/usr/sbin",
5042
5099
  "/sbin"
5043
5100
  ];
5044
- return Array.from(new Set(entries)).join(":");
5101
+ return Array.from(new Set(entries)).filter((e) => !isTmpPath(e)).join(":");
5045
5102
  }
5046
5103
  function xmlEscape(value) {
5047
5104
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
@@ -5300,7 +5357,7 @@ function formatBrokerServiceStatus(status) {
5300
5357
  return lines.join(`
5301
5358
  `);
5302
5359
  }
5303
- var DEFAULT_BROKER_HOST = "127.0.0.1", DEFAULT_BROKER_PORT = 65535, BROKER_SERVICE_POLL_INTERVAL_MS = 100, DEFAULT_BROKER_START_TIMEOUT_MS = 15000, DEFAULT_BROKER_URL;
5360
+ var DEFAULT_BROKER_HOST = "127.0.0.1", DEFAULT_BROKER_HOST_MESH = "0.0.0.0", DEFAULT_BROKER_PORT = 65535, DEFAULT_ADVERTISE_SCOPE = "local", BROKER_SERVICE_POLL_INTERVAL_MS = 100, DEFAULT_BROKER_START_TIMEOUT_MS = 15000, DEFAULT_BROKER_URL;
5304
5361
  var init_broker_service = __esm(async () => {
5305
5362
  init_support_paths();
5306
5363
  DEFAULT_BROKER_URL = buildDefaultBrokerUrl();
@@ -6195,7 +6252,7 @@ async function startLocalAgent(input) {
6195
6252
  const findMatchForRoot = (root) => {
6196
6253
  let fallback = null;
6197
6254
  for (const [id, override] of Object.entries(overrides)) {
6198
- if (BUILT_IN_LOCAL_AGENT_IDS.has(id))
6255
+ if (BUILT_IN_AGENT_DEFINITION_IDS.has(id))
6199
6256
  continue;
6200
6257
  if (!override.projectRoot)
6201
6258
  continue;
@@ -6435,7 +6492,7 @@ async function loadRegisteredLocalAgentBindings(nodeId, options = {}) {
6435
6492
  return results;
6436
6493
  }
6437
6494
  async function inferLocalAgentBinding(agentId, nodeId) {
6438
- if (!agentId || BUILT_IN_LOCAL_AGENT_IDS.has(agentId)) {
6495
+ if (!agentId || BUILT_IN_AGENT_DEFINITION_IDS.has(agentId)) {
6439
6496
  return null;
6440
6497
  }
6441
6498
  const overrides = await readRelayAgentOverrides();
@@ -6458,7 +6515,7 @@ async function ensureLocalAgentBindingOnline(agentId, nodeId, options = {}) {
6458
6515
  if (registeredBinding) {
6459
6516
  return registeredBinding;
6460
6517
  }
6461
- if (BUILT_IN_LOCAL_AGENT_IDS.has(agentId)) {
6518
+ if (BUILT_IN_AGENT_DEFINITION_IDS.has(agentId)) {
6462
6519
  return null;
6463
6520
  }
6464
6521
  if (options.includeDiscovered) {
@@ -6481,7 +6538,7 @@ async function ensureLocalAgentBindingOnline(agentId, nodeId, options = {}) {
6481
6538
  const onlineRecord = await ensureLocalAgentOnline(agentId, recordForHarness(localAgentRecordFromRelayAgentOverride(agentId, override), options.harness));
6482
6539
  return buildLocalAgentBinding(agentId, onlineRecord, isLocalAgentRecordOnline(agentId, onlineRecord), nodeId, "relay-agent-registry");
6483
6540
  }
6484
- var BUILT_IN_LOCAL_AGENT_IDS, MODULE_DIRECTORY, OPENSCOUT_REPO_ROOT, DEFAULT_LOCAL_AGENT_CAPABILITIES, DEFAULT_LOCAL_AGENT_HARNESS = "claude", SUPPORTED_LOCAL_AGENT_HARNESSES;
6541
+ var MODULE_DIRECTORY, OPENSCOUT_REPO_ROOT, DEFAULT_LOCAL_AGENT_CAPABILITIES, DEFAULT_LOCAL_AGENT_HARNESS = "claude", SUPPORTED_LOCAL_AGENT_HARNESSES;
6485
6542
  var init_local_agents = __esm(async () => {
6486
6543
  init_src();
6487
6544
  init_claude_stream_json();
@@ -6490,7 +6547,6 @@ var init_local_agents = __esm(async () => {
6490
6547
  init_support_paths();
6491
6548
  init_local_agent_template();
6492
6549
  await init_broker_service();
6493
- BUILT_IN_LOCAL_AGENT_IDS = new Set(["scout", "builder", "reviewer", "research"]);
6494
6550
  MODULE_DIRECTORY = dirname6(fileURLToPath5(import.meta.url));
6495
6551
  OPENSCOUT_REPO_ROOT = resolve4(MODULE_DIRECTORY, "..", "..", "..");
6496
6552
  DEFAULT_LOCAL_AGENT_CAPABILITIES = ["chat", "invoke", "deliver"];
@@ -8083,6 +8139,7 @@ function resolveScoutSurfaceCapabilities(surface) {
8083
8139
  }
8084
8140
 
8085
8141
  // apps/desktop/src/app/desktop/shell.ts
8142
+ init_src();
8086
8143
  init_setup();
8087
8144
  import { readFile as readFile6, readdir as readdir3, stat as stat4 } from "fs/promises";
8088
8145
  import { performance } from "perf_hooks";
@@ -8294,7 +8351,6 @@ var BROKER_SHARED_CHANNEL_ID = "channel.shared";
8294
8351
  var OPERATOR_ID = "operator";
8295
8352
  var DEFAULT_BROKER_HOST2 = "127.0.0.1";
8296
8353
  var DEFAULT_BROKER_PORT2 = 65535;
8297
- var BUILT_IN_SCOUT_AGENT_IDS = new Set([SCOUT_AGENT_ID, "builder", "reviewer", "research"]);
8298
8354
  function buildScoutBrokerUrlFromEnv() {
8299
8355
  const host = process.env.OPENSCOUT_BROKER_HOST ?? DEFAULT_BROKER_HOST2;
8300
8356
  const port = Number.parseInt(process.env.OPENSCOUT_BROKER_PORT ?? String(DEFAULT_BROKER_PORT2), 10);
@@ -8971,7 +9027,6 @@ function readProjectGitActivity(projectRoot) {
8971
9027
 
8972
9028
  // apps/desktop/src/app/desktop/shell.ts
8973
9029
  var OPERATOR_ID2 = "operator";
8974
- var BUILT_IN_ROLE_AGENT_IDS = new Set(["scout", "builder", "reviewer", "research"]);
8975
9030
  var RECENT_AGENT_ACTIVITY_WINDOW_SECONDS = 60 * 60 * 24 * 30;
8976
9031
  var RECONCILE_OFFLINE_WAIT_SECONDS = 60 * 3;
8977
9032
  var RECONCILE_NO_FOLLOW_UP_SECONDS = 60 * 10;
@@ -9182,7 +9237,7 @@ function interAgentThreadKey(participantIds) {
9182
9237
  function visibleRelayAgentIds(snapshot, configuredAgentIds, messagesByConversation, directActivity) {
9183
9238
  const visible = new Set([
9184
9239
  ...configuredAgentIds,
9185
- ...Array.from(BUILT_IN_ROLE_AGENT_IDS)
9240
+ ...Array.from(BUILT_IN_AGENT_DEFINITION_IDS)
9186
9241
  ]);
9187
9242
  const cutoff = Math.floor(Date.now() / 1000) - RECENT_AGENT_ACTIVITY_WINDOW_SECONDS;
9188
9243
  for (const [agentId, activity] of directActivity.entries()) {
@@ -11231,7 +11286,6 @@ var SCOUT_BROKER_OPERATOR_ID = "operator";
11231
11286
  var SCOUT_SHARED_CHANNEL_ID = "channel.shared";
11232
11287
  var SCOUT_VOICE_CHANNEL_ID = "channel.voice";
11233
11288
  var SCOUT_SYSTEM_CHANNEL_ID = "channel.system";
11234
- var SCOUT_AGENT_ID2 = "scout";
11235
11289
  function resolveCurrentDirectory(input) {
11236
11290
  return input?.trim() || process.cwd();
11237
11291
  }
@@ -11467,14 +11521,14 @@ async function ensureDirectConversation(baseUrl, snapshot, nodeId, agentId, oper
11467
11521
  const definition = {
11468
11522
  id: conversationId,
11469
11523
  kind: "direct",
11470
- title: agentId === SCOUT_AGENT_ID2 ? "Scout" : actorDisplayName2(snapshot, agentId, operatorName),
11524
+ title: agentId === SCOUT_AGENT_ID ? "Scout" : actorDisplayName2(snapshot, agentId, operatorName),
11471
11525
  visibility: "private",
11472
11526
  shareMode: nextShareMode,
11473
11527
  authorityNodeId: nodeId,
11474
11528
  participantIds: [SCOUT_BROKER_OPERATOR_ID, agentId].sort(),
11475
11529
  metadata: {
11476
11530
  surface: "scout-desktop",
11477
- ...agentId === SCOUT_AGENT_ID2 ? { role: "partner" } : {}
11531
+ ...agentId === SCOUT_AGENT_ID ? { role: "partner" } : {}
11478
11532
  }
11479
11533
  };
11480
11534
  await postBrokerJson(baseUrl, "/v1/conversations", definition);
@@ -11681,7 +11735,7 @@ async function sendScoutDesktopRelayMessage(input, options = {}) {
11681
11735
  await ensureCoreConversation(broker.baseUrl, broker.snapshot, broker.node.id, SCOUT_SYSTEM_CHANNEL_ID);
11682
11736
  const directTarget = input.destinationKind === "direct" ? input.destinationId : null;
11683
11737
  if (directTarget) {
11684
- if (directTarget === SCOUT_AGENT_ID2) {
11738
+ if (directTarget === SCOUT_AGENT_ID) {
11685
11739
  await ensureScoutRelayAgentConfigured({ currentDirectory });
11686
11740
  }
11687
11741
  await ensureBrokerAgentBinding(broker.baseUrl, broker.snapshot, broker.node.id, directTarget, currentDirectory);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openscout/scout",
3
- "version": "0.2.37",
3
+ "version": "0.2.40",
4
4
  "description": "Published Scout package that installs the `scout` command",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -23,6 +23,6 @@
23
23
  "access": "public"
24
24
  },
25
25
  "dependencies": {
26
- "@openscout/runtime": "0.2.37"
26
+ "@openscout/runtime": "0.2.40"
27
27
  }
28
28
  }
@@ -1 +0,0 @@
1
- :root{--bg: #F9F9F8;--surface: #FFFFFF;--ink: #1C1C1A;--muted: #8A8A86;--dim: #C4C4C0;--border: #E4E4E2;--accent: #0066FF;--accent-soft: rgba(0, 102, 255, .08);--green: #22c55e;--red: #dc2626;--radius: 8px;--shadow-soft: rgba(24, 24, 22, .06);--sidebar-w: 280px;--font-sans: "Inter", ui-sans-serif, system-ui, -apple-system, sans-serif;--font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;--font-serif: "Spectral", Georgia, serif;font-family:var(--font-sans);font-size:13px;line-height:1.5;color:var(--ink);background:var(--bg);-webkit-font-smoothing:antialiased}*{box-sizing:border-box;margin:0}body{margin:0}.s-app{display:flex;height:100vh;overflow:hidden}.s-sidebar{width:var(--sidebar-w);flex-shrink:0;display:flex;flex-direction:column;border-right:1px solid var(--border);background:var(--surface);height:100vh;overflow:hidden}.s-content{flex:1;min-width:0;height:100vh;overflow-y:auto;background:var(--bg)}.s-sidebar-header{padding:16px 16px 12px;flex-shrink:0}.s-logo{font-family:var(--font-serif);font-size:18px;font-weight:600;letter-spacing:-.02em;cursor:pointer;-webkit-user-select:none;user-select:none}.s-sidebar-footer{flex-shrink:0;padding:8px;border-top:1px solid var(--border)}.s-nav-item{display:flex;align-items:center;gap:8px;width:100%;border:none;background:none;padding:6px 8px;border-radius:6px;font-family:var(--font-sans);font-size:12px;font-weight:500;color:var(--muted);cursor:pointer;transition:background .12s ease,color .12s ease}.s-nav-item:hover{background:var(--bg);color:var(--ink)}.s-nav-item-active{background:var(--accent-soft);color:var(--accent)}.s-sidebar-label{padding:4px 16px 6px;font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--dim);flex-shrink:0}.s-sidebar-list{flex:1;overflow-y:auto;padding-bottom:12px}.s-sidebar-empty{padding:24px 16px;text-align:center;font-size:11px;color:var(--dim)}.s-sidebar-row{display:flex;align-items:center;gap:8px;padding:8px 12px;margin:0 6px;border-radius:6px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .1s ease}.s-sidebar-row:hover{background:var(--bg)}.s-sidebar-row-active,.s-sidebar-row-active:hover{background:var(--accent-soft)}.s-sidebar-row-body{flex:1;min-width:0}.s-sidebar-row-header{display:flex;align-items:center;gap:5px}.s-sidebar-row-name{font-size:12px;font-weight:600;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.s-sidebar-row-preview{font-size:11px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:1px;line-height:1.3}.s-sidebar-row-preview-empty{font-style:italic;color:var(--dim)}.s-sidebar-row-time{font-size:10px;color:var(--dim);font-family:var(--font-mono);flex-shrink:0;align-self:flex-start;margin-top:2px}.s-welcome{display:flex;align-items:center;justify-content:center;height:100%;color:var(--dim)}.s-welcome-inner{text-align:center}.s-welcome h2{font-family:var(--font-serif);font-size:24px;font-weight:600;color:var(--dim);margin-bottom:4px}.s-welcome p{font-size:12px}.s-home{padding:32px;height:100vh;overflow-y:auto}.s-home-header{margin-bottom:32px}.s-home-header h2{font-family:var(--font-serif);font-size:22px;font-weight:600;color:var(--ink);margin-bottom:4px}.s-home-header p{font-size:12px;color:var(--muted)}.s-home-section{margin-bottom:28px}.s-home-section-title{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--dim);margin-bottom:10px}.s-home-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;max-width:480px}.s-home-card-row{display:flex;align-items:center;gap:10px;padding:10px 14px;font-size:12px}.s-home-card-row+.s-home-card-row{border-top:1px solid var(--border)}.s-home-card-row-label{color:var(--muted);font-size:11px;min-width:80px;flex-shrink:0}.s-home-card-row-value{color:var(--ink);font-family:var(--font-mono);font-size:11px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.s-home-steps{list-style:none;padding:0;max-width:480px}.s-home-steps li{display:flex;align-items:baseline;gap:10px;padding:6px 0;font-size:12px;color:var(--ink);line-height:1.5}.s-home-steps li:before{content:attr(data-step);font-size:10px;font-weight:700;font-family:var(--font-mono);color:var(--muted);flex-shrink:0;width:18px;height:18px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:var(--bg);border:1px solid var(--border)}.s-home-steps code{font-family:var(--font-mono);font-size:11px;background:var(--bg);border:1px solid var(--border);border-radius:4px;padding:1px 5px}.s-home-card-row-clickable{cursor:pointer;transition:background .1s ease}.s-home-card-row-clickable:hover{background:var(--bg)}.s-activity-stream{max-width:560px}.s-activity-row{display:flex;align-items:baseline;gap:8px;padding:4px 0;font-size:12px;line-height:1.5}.s-activity-row-clickable{cursor:pointer;border-radius:4px;padding:4px 6px;margin:0 -6px;transition:background .1s ease}.s-activity-row-clickable:hover{background:var(--surface)}.s-activity-time{font-size:10px;color:var(--dim);font-family:var(--font-mono);flex-shrink:0;min-width:36px}.s-activity-actor{font-weight:600;color:var(--ink);flex-shrink:0}.s-activity-kind{color:var(--muted)}.s-activity-title{color:var(--muted);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.s-activity-list{max-width:560px}.s-activity-list-row{display:flex;align-items:flex-start;gap:10px;padding:8px 0}.s-activity-list-item+.s-activity-list-item{border-top:1px solid var(--border)}.s-activity-list-row-clickable{cursor:pointer;border-radius:6px;padding:8px;margin:0 -8px;transition:background .1s ease}.s-activity-list-row-clickable:hover{background:var(--surface)}.s-activity-list-body{flex:1;min-width:0}.s-activity-list-header{display:flex;align-items:baseline;gap:6px}.s-activity-list-actor{font-size:12px;font-weight:600;color:var(--ink)}.s-activity-list-kind{font-size:11px;color:var(--muted)}.s-activity-list-title{font-size:12px;color:var(--ink);margin-top:2px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.s-activity-list-summary{font-size:11px;color:var(--muted);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.s-activity-expanded{padding:4px 8px 12px 38px}.s-activity-expanded-summary{font-size:12px;color:var(--ink);margin-bottom:8px;line-height:1.4}.s-activity-expanded-meta{display:flex;gap:8px;font-size:11px;padding:2px 0}.s-activity-meta-label{color:var(--muted);min-width:56px}.s-activity-meta-value{color:var(--ink);word-break:break-all}.s-activity-expanded-actions{margin-top:8px}.s-btn-sm{font-size:11px;padding:4px 10px}.s-error{color:var(--red);font-size:12px;padding:8px 12px;background:#fef2f2;border:1px solid #fecaca;border-radius:var(--radius);margin:12px}.s-empty{padding:32px 0;color:var(--muted);font-size:12px}.s-empty p:first-child{font-size:13px;font-weight:500;color:var(--ink);margin-bottom:4px}.s-meta{font-size:11px;color:var(--muted);font-family:var(--font-mono)}.s-spacer{flex:1}.s-dot{display:inline-block;width:6px;height:6px;border-radius:50%;flex-shrink:0}.s-dot-sm{width:5px;height:5px}.s-badge{font-size:10px;font-family:var(--font-mono);color:var(--muted);background:var(--bg);border-radius:4px;padding:1px 6px;flex-shrink:0;text-transform:uppercase;letter-spacing:.04em}.s-time{font-size:10px;color:var(--dim);font-family:var(--font-mono);flex-shrink:0;letter-spacing:.01em}.s-back{border:none;background:none;padding:0;font-family:var(--font-sans);font-size:12px;font-weight:500;color:var(--muted);cursor:pointer;transition:color .12s ease}.s-back:hover{color:var(--ink)}.s-chevron{width:12px;height:12px;flex-shrink:0;position:relative;opacity:.3;transition:opacity .14s ease}.s-chevron:before{content:"";position:absolute;top:3px;left:2px;width:6px;height:6px;border-right:1.5px solid var(--ink);border-bottom:1.5px solid var(--ink);transform:rotate(-45deg)}.s-avatar{width:32px;height:32px;border-radius:50%;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;color:#fff}.s-avatar-sm{width:28px;height:28px;font-size:11px}.s-avatar-lg{width:56px;height:56px;font-size:20px}.s-conversation{display:flex;flex-direction:column;height:100vh}.s-conv-header{display:flex;align-items:center;gap:10px;padding:10px 20px;border-bottom:1px solid var(--border);background:var(--bg);flex-shrink:0;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .12s ease}.s-conv-header:hover{background:#f6f6f5}.s-conv-header .s-back{margin-right:2px;font-size:16px;line-height:1}.s-conv-header-info{flex:1;min-width:0}.s-conv-header-name{font-size:13px;font-weight:600;color:var(--ink)}.s-conv-header-state{display:flex;align-items:center;gap:4px;font-size:11px;color:var(--muted);margin-top:1px}.s-conv-status{display:flex;align-items:center;gap:10px;padding:10px 20px;border-bottom:1px solid var(--border);flex-shrink:0}.s-conv-status-pending{background:#0066ff0f;border-bottom-color:#0066ff1f}.s-conv-status-working{background:#22c55e0f;border-bottom-color:#22c55e24}.s-conv-status-offline{background:#1118270a;border-bottom-color:#11182714}.s-conv-status-dot{width:8px;height:8px;border-radius:50%;background:currentColor;color:var(--accent);flex-shrink:0}.s-conv-status-working .s-conv-status-dot{color:var(--green);animation:s-pulse 1.4s ease-in-out infinite}.s-conv-status-offline .s-conv-status-dot{color:var(--dim)}.s-conv-status-copy{display:flex;flex-direction:column;min-width:0;gap:2px}.s-conv-status-label{font-size:11px;font-weight:700;color:var(--ink)}.s-conv-status-detail{font-size:11px;color:var(--muted);line-height:1.4}.s-messages{flex:1;overflow-y:auto;padding:16px 20px;display:flex;flex-direction:column;gap:6px}.s-msg{max-width:85%;align-self:flex-start}.s-msg-you{align-self:flex-end}.s-msg-header{display:flex;align-items:baseline;gap:6px;margin-bottom:2px;padding:0 2px}.s-msg-actor{font-size:11px;font-weight:600;color:var(--ink)}.s-msg-time{font-size:10px;color:var(--dim);font-family:var(--font-mono)}.s-msg-body{font-size:12px;line-height:1.5;color:var(--ink);white-space:pre-wrap;word-break:break-word;padding:8px 12px;border-radius:14px 14px 14px 4px;background:var(--surface);border:1px solid var(--border)}.s-msg-you .s-msg-body{border-radius:14px 14px 4px;background:var(--accent-soft);border-color:#0066ff1f}.s-msg-you .s-msg-header{justify-content:flex-end}.s-msg-working{max-width:85%;align-self:flex-start}.s-msg-working-body{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:14px 14px 14px 4px;background:linear-gradient(135deg,#22c55e14,#22c55e0a);border:1px solid rgba(34,197,94,.14)}.s-msg-working-copy{font-size:12px;line-height:1.45;color:var(--ink)}.s-typing-indicator{display:inline-flex;align-items:center;gap:4px;flex-shrink:0}.s-typing-dot{width:6px;height:6px;border-radius:50%;background:var(--green);opacity:.35;animation:s-typing-bounce 1.1s ease-in-out infinite}.s-typing-dot:nth-child(2){animation-delay:.14s}.s-typing-dot:nth-child(3){animation-delay:.28s}@keyframes s-typing-bounce{0%,80%,to{opacity:.35;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}.s-compose{display:flex;align-items:flex-end;gap:8px;padding:10px 20px;border-top:1px solid var(--border);background:var(--bg);flex-shrink:0}.s-compose-input{flex:1;border:1px solid var(--border);background:var(--surface);border-radius:20px;min-height:40px;max-height:160px;padding:10px 14px;font-family:var(--font-sans);font-size:12px;line-height:1.45;color:var(--ink);outline:none;transition:border-color .12s ease;resize:none;overflow-y:hidden;white-space:pre-wrap}.s-compose-input:focus{border-color:var(--accent)}.s-compose-input:disabled{opacity:.5;cursor:not-allowed}.s-compose-send{width:32px;height:32px;border-radius:50%;border:none;background:var(--ink);color:#fff;font-size:14px;font-weight:700;cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:opacity .12s ease}.s-compose-send svg{display:block}.s-compose-send:disabled{opacity:.3;cursor:not-allowed}.s-agent-profile{display:flex;flex-direction:column;align-items:flex-start;padding:8px 0 16px;gap:4px}.s-agent-profile-name{font-size:18px;font-weight:600;color:var(--ink);margin-top:8px}.s-agent-profile-handle{font-size:12px;font-family:var(--font-mono);color:var(--muted)}.s-agent-profile-state{display:flex;align-items:center;gap:5px;font-size:12px;color:var(--muted);margin-top:4px}.s-agent-details{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;margin-top:16px;max-width:480px}.s-detail-row{display:flex;align-items:baseline;justify-content:space-between;padding:7px 14px;font-size:12px;gap:12px}.s-detail-row+.s-detail-row{border-top:1px solid var(--border)}.s-detail-label{color:var(--muted);flex-shrink:0;font-size:11px}.s-detail-value{color:var(--ink);font-family:var(--font-mono);font-size:11px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.s-section-title{font-size:15px;font-weight:600;color:var(--ink);margin-bottom:16px}.s-actions{display:flex;gap:8px;margin-bottom:16px}.s-btn{border:1px solid var(--border);background:var(--surface);padding:6px 14px;border-radius:var(--radius);font-family:var(--font-sans);font-size:12px;font-weight:500;cursor:pointer;transition:all .14s cubic-bezier(.16,1,.3,1)}.s-btn:hover{border-color:var(--dim);box-shadow:0 1px 2px var(--shadow-soft)}.s-btn:disabled{opacity:.4;cursor:not-allowed}.s-btn-primary{background:var(--ink);color:var(--bg);border-color:var(--ink)}.s-btn-primary:hover{background:#2a2a28;box-shadow:0 2px 6px var(--shadow-soft)}.s-qr{max-width:240px;margin:20px 0;padding:16px;background:var(--surface);border:1px solid var(--border);border-radius:12px;box-shadow:0 2px 6px var(--shadow-soft)}.s-qr svg{display:block;width:100%;height:auto}.s-pair-meta{max-width:360px;margin:0;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}.s-pair-row{display:flex;align-items:center;justify-content:space-between;padding:7px 14px;font-size:12px}.s-pair-row+.s-pair-row{border-top:1px solid var(--border)}.s-pair-label{color:var(--muted);flex-shrink:0}.s-pair-value{display:flex;align-items:center;color:var(--ink);text-align:right;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.s-pair-mono{font-family:var(--font-mono);font-size:11px}.s-sidebar-nav{padding:0 8px 4px;flex-shrink:0}.s-nav-badge{font-size:10px;font-weight:600;font-family:var(--font-mono);color:#fff;background:var(--green);border-radius:10px;padding:0 6px;min-width:18px;text-align:center;line-height:16px;margin-left:auto}.s-sidebar-avatar-wrap{position:relative;flex-shrink:0}.s-task-indicator{position:absolute;bottom:-1px;right:-1px;width:8px;height:8px;border-radius:50%;background:var(--green);border:2px solid var(--surface)}.s-sidebar-row-active .s-task-indicator{border-color:#0066ff14}.s-flight-banner{display:flex;align-items:center;gap:6px;padding:6px 20px;background:#22c55e0f;border-bottom:1px solid rgba(34,197,94,.12);font-size:11px;flex-shrink:0}.s-flight-banner-dot{width:6px;height:6px;border-radius:50%;background:var(--green);flex-shrink:0;animation:s-pulse 2s ease-in-out infinite}@keyframes s-pulse{0%,to{opacity:1}50%{opacity:.4}}.s-flight-banner-label{font-weight:600;color:var(--ink)}.s-flight-banner-summary{color:var(--muted);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.s-flights{border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}.s-flight-row{display:flex;align-items:center;gap:10px;padding:10px 14px;background:var(--surface);cursor:pointer;transition:background .12s ease}.s-flight-row:hover{background:#f6f6f5}.s-flight-row+.s-flight-row{border-top:1px solid var(--border)}.s-flight-body{flex:1;min-width:0}.s-flight-header{display:flex;align-items:center;gap:6px}.s-flight-name{font-size:12px;font-weight:600;color:var(--ink)}.s-flight-state{font-size:11px;font-family:var(--font-mono);font-weight:500}.s-flight-summary{font-size:11px;color:var(--muted);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.s-content>div:not(.s-conversation):not(.s-welcome):not(.s-home):not(.s-agents-layout){padding:24px 32px;max-width:640px}.s-agents-layout{display:flex;height:100vh;overflow:hidden}.s-agents-list-panel{width:100%;height:100vh;overflow-y:auto;padding:24px 16px;transition:width .15s ease}.s-agents-layout-split .s-agents-list-panel{width:280px;flex-shrink:0;border-right:1px solid var(--border);padding:16px 8px}.s-agents-detail-panel{flex:1;min-width:0;height:100vh;overflow-y:auto;padding:24px 32px}.s-agent-list-row{display:flex;align-items:center;gap:10px;padding:8px;border-radius:6px;cursor:pointer;transition:background .1s ease}.s-agent-list-row:hover{background:var(--bg)}.s-agent-list-row-active,.s-agent-list-row-active:hover{background:var(--accent-soft)}.s-agent-list-body{flex:1;min-width:0}.s-agent-list-header{display:flex;align-items:center;gap:5px}.s-agent-list-name{font-size:12px;font-weight:600;color:var(--ink)}.s-agent-list-qualifier{font-size:10px;font-family:var(--font-mono);color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.s-agent-list-meta{display:flex;align-items:center;gap:8px;margin-top:1px;font-size:11px;color:var(--muted)}.s-agent-list-meta span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.s-agent-detail-header{display:flex;align-items:center;gap:16px;margin-bottom:20px}.s-agent-detail-name{font-size:18px;font-weight:600;color:var(--ink);display:flex;align-items:baseline;gap:8px}.s-agent-detail-qualifier{font-size:12px;font-family:var(--font-mono);color:var(--dim);font-weight:400}.s-agent-detail-state{display:flex;align-items:center;gap:5px;font-size:12px;color:var(--muted);margin-top:2px}.s-agent-detail-meta{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;max-width:480px}.s-agent-detail-section{margin-top:20px}.s-agent-detail-messages{max-width:480px}.s-agent-detail-msg{display:flex;align-items:baseline;gap:6px;padding:4px 0;font-size:12px}.s-agent-detail-msg-clickable{cursor:pointer;border-radius:4px;margin:0 -4px;padding:4px}.s-agent-detail-msg-clickable:hover{background:var(--hover)}.s-agent-detail-msg+.s-agent-detail-msg{border-top:1px solid var(--border)}.s-agent-detail-msg-actor{font-weight:600;color:var(--ink);flex-shrink:0}.s-agent-detail-msg-body{color:var(--muted);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(max-width:767px){.s-sidebar{width:100%;position:absolute;inset:0;z-index:20;transition:transform .2s cubic-bezier(.16,1,.3,1)}.s-content{position:absolute;inset:0;z-index:10;transform:translate(100%);transition:transform .2s cubic-bezier(.16,1,.3,1)}.s-app{position:relative}.s-app-content-open .s-sidebar{transform:translate(-100%)}.s-app-content-open .s-content{transform:translate(0)}.s-conv-header .s-back{display:block}}@media(min-width:768px){.s-conv-header .s-back{display:none}}.s-sessions-screen,.s-mesh-screen{padding:20px 24px}.s-sessions-header{display:flex;align-items:baseline;gap:12px;margin-bottom:16px}.s-page-title{font-size:18px;font-weight:600;letter-spacing:-.01em}.s-session-participants{font-size:10px;font-family:var(--font-mono);color:var(--dim);margin-top:2px}.s-filter-bar{display:flex;gap:6px;margin-bottom:16px;overflow-x:auto}.s-filter-chip{font-size:11px;font-weight:500;padding:4px 12px;border-radius:20px;border:1px solid var(--border);background:var(--surface);color:var(--muted);cursor:pointer;flex-shrink:0;transition:background .15s,color .15s}.s-filter-chip:hover{background:var(--bg)}.s-filter-chip-active{background:var(--accent);color:#fff;border-color:var(--accent)}.s-filter-chip-active:hover{background:var(--accent)}.s-mesh-status-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:4px 0;margin-bottom:16px}.s-mesh-warnings{display:flex;flex-direction:column;gap:8px;margin-bottom:16px}.s-mesh-warning{font-size:12px;line-height:1.55;padding:10px 14px;border-radius:var(--radius);background:#f59e0b14;color:#92400e;border:1px solid rgba(245,158,11,.2)}.s-mesh-section{margin-bottom:20px}.s-mesh-section-title{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin-bottom:10px;display:flex;align-items:center}.s-mesh-nodes{display:flex;flex-direction:column;gap:6px}.s-mesh-node{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:10px 14px}.s-mesh-node-local{border-color:var(--accent);border-width:1.5px}.s-mesh-node-header{display:flex;align-items:center;gap:8px}.s-mesh-node-name{font-size:13px;font-weight:500}.s-mesh-node-detail{font-size:11px;color:var(--muted);margin-top:3px;padding-left:14px}::-webkit-scrollbar{width:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--muted)}