@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.
- package/dist/control-plane-client/assets/arc.es-C-s36DjK.js +188 -0
- package/dist/control-plane-client/assets/index--5UC57U9.css +1 -0
- package/dist/control-plane-client/assets/index-B2VbvZaM.js +9 -0
- package/dist/control-plane-client/index.html +2 -2
- package/dist/main.mjs +114 -45
- package/dist/pair-supervisor.mjs +86 -35
- package/dist/scout-control-plane-web.mjs +86 -35
- package/dist/scout-web-server.mjs +100 -46
- package/package.json +2 -2
- package/dist/control-plane-client/assets/index-BA2r5hxl.css +0 -1
- package/dist/control-plane-client/assets/index-RH3faelc.js +0 -9
|
@@ -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
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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 ||
|
|
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(([
|
|
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:
|
|
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:
|
|
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 (
|
|
3724
|
-
overrides[SCOUT_AGENT_ID]
|
|
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,
|
|
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
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
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
|
|
4939
|
-
const
|
|
4940
|
-
const
|
|
4941
|
-
const controlHome =
|
|
4942
|
-
const
|
|
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("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
@@ -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 (
|
|
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 ||
|
|
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 (
|
|
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
|
|
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(
|
|
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 ===
|
|
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 ===
|
|
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 ===
|
|
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.
|
|
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.
|
|
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)}
|