@openscout/scout 0.2.46 → 0.2.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.mjs CHANGED
@@ -382,6 +382,53 @@ function parseWatchCommandOptions(args, defaultCurrentDirectory) {
382
382
  channel
383
383
  };
384
384
  }
385
+ function parseLatestCommandOptions(args, defaultCurrentDirectory) {
386
+ const parsed = parseContextRootPrefix(args, defaultCurrentDirectory);
387
+ let agentId;
388
+ let actorId;
389
+ let conversationId;
390
+ let limit = 12;
391
+ for (let index = 0;index < parsed.args.length; index += 1) {
392
+ const current = parsed.args[index] ?? "";
393
+ if (current === "--agent" || current.startsWith("--agent=")) {
394
+ const value = parseFlagValue(parsed.args, index, "--agent");
395
+ agentId = value.value;
396
+ index = value.nextIndex;
397
+ continue;
398
+ }
399
+ if (current === "--actor" || current.startsWith("--actor=")) {
400
+ const value = parseFlagValue(parsed.args, index, "--actor");
401
+ actorId = value.value;
402
+ index = value.nextIndex;
403
+ continue;
404
+ }
405
+ if (current === "--conversation" || current.startsWith("--conversation=")) {
406
+ const value = parseFlagValue(parsed.args, index, "--conversation");
407
+ conversationId = value.value;
408
+ index = value.nextIndex;
409
+ continue;
410
+ }
411
+ if (current === "--limit" || current.startsWith("--limit=")) {
412
+ const value = parseFlagValue(parsed.args, index, "--limit");
413
+ const parsedLimit = Number.parseInt(value.value, 10);
414
+ if (!Number.isFinite(parsedLimit) || parsedLimit <= 0) {
415
+ throw new ScoutCliError(`invalid limit: ${value.value}`);
416
+ }
417
+ limit = parsedLimit;
418
+ index = value.nextIndex;
419
+ continue;
420
+ }
421
+ unexpectedArgs("latest", args);
422
+ }
423
+ return {
424
+ currentDirectory: parsed.currentDirectory,
425
+ args: parsed.args,
426
+ agentId,
427
+ actorId,
428
+ conversationId,
429
+ limit
430
+ };
431
+ }
385
432
  function parseEnrollCommandOptions(args, defaultCurrentDirectory) {
386
433
  const parsed = parseContextRootPrefix(args, defaultCurrentDirectory);
387
434
  let agentName = null;
@@ -10597,6 +10644,63 @@ function renderScoutBroadcastResult(result) {
10597
10644
  return lines.join(`
10598
10645
  `);
10599
10646
  }
10647
+ function renderScoutActivityKind(kind) {
10648
+ switch (kind) {
10649
+ case "ask_opened":
10650
+ return "asked";
10651
+ case "ask_working":
10652
+ return "working";
10653
+ case "ask_replied":
10654
+ return "replied";
10655
+ case "ask_failed":
10656
+ return "failed";
10657
+ case "handoff_sent":
10658
+ return "handoff";
10659
+ case "agent_message":
10660
+ return "agent";
10661
+ case "status_message":
10662
+ return "status";
10663
+ case "invocation_recorded":
10664
+ return "invoke";
10665
+ case "flight_updated":
10666
+ return "flight";
10667
+ case "collaboration_event":
10668
+ return "collab";
10669
+ case "message_posted":
10670
+ default:
10671
+ return "message";
10672
+ }
10673
+ }
10674
+ function renderScoutActivityParticipants(item) {
10675
+ const actor = item.actorId?.trim();
10676
+ const counterpart = item.counterpartId?.trim();
10677
+ if (actor && counterpart && actor !== counterpart) {
10678
+ return `${actor} -> ${counterpart}`;
10679
+ }
10680
+ return actor || counterpart || item.agentId?.trim() || null;
10681
+ }
10682
+ function renderScoutActivityItem(item) {
10683
+ const timestamp = normalizeUnixTimestamp2(item.ts) ?? Math.floor(Date.now() / 1000);
10684
+ const label = renderScoutActivityKind(item.kind).padEnd(7, " ");
10685
+ const participants = renderScoutActivityParticipants(item);
10686
+ const title = item.title?.trim() || item.summary?.trim() || item.kind;
10687
+ const summary = item.summary?.trim();
10688
+ const detail = summary && summary !== title ? summary : null;
10689
+ return [
10690
+ formatScoutTimestamp(timestamp),
10691
+ label,
10692
+ participants,
10693
+ title,
10694
+ detail ? `(${detail})` : null
10695
+ ].filter(Boolean).join(" ");
10696
+ }
10697
+ function renderScoutActivityList(items) {
10698
+ if (items.length === 0) {
10699
+ return "No Scout activity yet.";
10700
+ }
10701
+ return items.map(renderScoutActivityItem).join(`
10702
+ `);
10703
+ }
10600
10704
  var init_broker = () => {};
10601
10705
 
10602
10706
  // ../../apps/desktop/src/cli/commands/broadcast.ts
@@ -11781,6 +11885,28 @@ var init_env = __esm(async () => {
11781
11885
  await init_service();
11782
11886
  });
11783
11887
 
11888
+ // ../../apps/desktop/src/cli/commands/latest.ts
11889
+ var exports_latest = {};
11890
+ __export(exports_latest, {
11891
+ runLatestCommand: () => runLatestCommand
11892
+ });
11893
+ async function runLatestCommand(context, args) {
11894
+ const options = parseLatestCommandOptions(args, defaultScoutContextDirectory(context));
11895
+ const items = await loadScoutActivityItems({
11896
+ agentId: options.agentId,
11897
+ actorId: options.actorId,
11898
+ conversationId: options.conversationId,
11899
+ limit: options.limit
11900
+ });
11901
+ context.output.writeValue(items, renderScoutActivityList);
11902
+ }
11903
+ var init_latest = __esm(async () => {
11904
+ init_context();
11905
+ init_options();
11906
+ init_broker();
11907
+ await init_service();
11908
+ });
11909
+
11784
11910
  // ../runtime/src/tailscale.ts
11785
11911
  import { readFile as readFile8 } from "fs/promises";
11786
11912
  import { execFile } from "child_process";
@@ -41167,11 +41293,12 @@ __export(exports_server, {
41167
41293
  runServerCommand: () => runServerCommand,
41168
41294
  resolveScoutWebServerEntry: () => resolveScoutWebServerEntry,
41169
41295
  resolveScoutControlPlaneWebServerEntry: () => resolveScoutControlPlaneWebServerEntry,
41170
- renderServerCommandHelp: () => renderServerCommandHelp
41296
+ renderServerCommandHelp: () => renderServerCommandHelp,
41297
+ normalizeServerOpenPath: () => normalizeServerOpenPath
41171
41298
  });
41172
41299
  import { spawn as spawn5 } from "child_process";
41173
41300
  import { existsSync as existsSync16 } from "fs";
41174
- import { dirname as dirname10, join as join24 } from "path";
41301
+ import { dirname as dirname10, join as join24, resolve as resolve9 } from "path";
41175
41302
  import { fileURLToPath as fileURLToPath7 } from "url";
41176
41303
  function renderServerCommandHelp() {
41177
41304
  return [
@@ -41179,11 +41306,15 @@ function renderServerCommandHelp() {
41179
41306
  "",
41180
41307
  "Usage:",
41181
41308
  " scout server start [options]",
41309
+ " scout server open [options]",
41182
41310
  " scout server control-plane start [options]",
41311
+ " scout server control-plane open [options]",
41183
41312
  "",
41184
41313
  "Subcommands:",
41185
41314
  " start Full desktop web API + UI assets (default stack).",
41315
+ " open Open the full web UI and start it on demand if needed.",
41186
41316
  " control-plane start Pairing + relay/shell activity only (`@openscout/web` surface).",
41317
+ " control-plane open Open the control-plane UI and start it on demand if needed.",
41187
41318
  "",
41188
41319
  "Options:",
41189
41320
  " --port <n> Listen port (default 3200; env SCOUT_WEB_PORT)",
@@ -41191,6 +41322,7 @@ function renderServerCommandHelp() {
41191
41322
  " --static-root DIR Static client root (env SCOUT_STATIC_ROOT)",
41192
41323
  " --vite-url URL Dev proxy target for non-API routes (env SCOUT_VITE_URL)",
41193
41324
  " --cwd DIR Workspace / setup root (env OPENSCOUT_SETUP_CWD)",
41325
+ " --path PATH Browser path for `open` (default /)",
41194
41326
  "",
41195
41327
  "Requires `bun` on PATH.",
41196
41328
  "Published installs include dist/client for the full web UI and dist/control-plane-client",
@@ -41223,8 +41355,9 @@ function resolveScoutControlPlaneWebServerEntry() {
41223
41355
  }
41224
41356
  throw new ScoutCliError("Could not find Scout control-plane web server entry. Rebuild @openscout/scout or run from the OpenScout repository.");
41225
41357
  }
41226
- function parseServerStartFlags(args) {
41358
+ function parseServerFlags(args) {
41227
41359
  const env = {};
41360
+ let openPath = "/";
41228
41361
  for (let i = 0;i < args.length; i++) {
41229
41362
  const a = args[i];
41230
41363
  if (a === "--port") {
@@ -41259,9 +41392,36 @@ function parseServerStartFlags(args) {
41259
41392
  env.OPENSCOUT_SETUP_CWD = v;
41260
41393
  continue;
41261
41394
  }
41395
+ if (a === "--path") {
41396
+ const v = args[++i];
41397
+ if (!v)
41398
+ throw new ScoutCliError("--path requires a value");
41399
+ openPath = v;
41400
+ continue;
41401
+ }
41402
+ if (a.startsWith("--port=")) {
41403
+ env.SCOUT_WEB_PORT = a.slice("--port=".length);
41404
+ continue;
41405
+ }
41406
+ if (a.startsWith("--static-root=")) {
41407
+ env.SCOUT_STATIC_ROOT = a.slice("--static-root=".length);
41408
+ continue;
41409
+ }
41410
+ if (a.startsWith("--vite-url=")) {
41411
+ env.SCOUT_VITE_URL = a.slice("--vite-url=".length);
41412
+ continue;
41413
+ }
41414
+ if (a.startsWith("--cwd=")) {
41415
+ env.OPENSCOUT_SETUP_CWD = a.slice("--cwd=".length);
41416
+ continue;
41417
+ }
41418
+ if (a.startsWith("--path=")) {
41419
+ openPath = a.slice("--path=".length);
41420
+ continue;
41421
+ }
41262
41422
  throw new ScoutCliError(`unknown option: ${a}`);
41263
41423
  }
41264
- return { env };
41424
+ return { env, openPath };
41265
41425
  }
41266
41426
  function resolveBundledStaticClientRoot(entry, mode) {
41267
41427
  const entryDir = dirname10(entry);
@@ -41269,29 +41429,7 @@ function resolveBundledStaticClientRoot(entry, mode) {
41269
41429
  const indexPath = join24(clientDirectory, "index.html");
41270
41430
  return existsSync16(indexPath) ? clientDirectory : null;
41271
41431
  }
41272
- async function runServerCommand(context, args) {
41273
- if (args.length === 0 || args[0] === "help" || args[0] === "--help" || args[0] === "-h") {
41274
- context.output.writeText(renderServerCommandHelp());
41275
- return;
41276
- }
41277
- let flagArgs;
41278
- let entry;
41279
- let mode;
41280
- if (args[0] === "start") {
41281
- flagArgs = args.slice(1);
41282
- entry = resolveScoutWebServerEntry();
41283
- mode = "full";
41284
- } else if (args[0] === "control-plane") {
41285
- if (args[1] !== "start") {
41286
- throw new ScoutCliError("expected: scout server control-plane start");
41287
- }
41288
- flagArgs = args.slice(2);
41289
- entry = resolveScoutControlPlaneWebServerEntry();
41290
- mode = "control-plane";
41291
- } else {
41292
- throw new ScoutCliError(`unknown subcommand: ${args[0]} (try: scout server start)`);
41293
- }
41294
- const { env: flagEnv } = parseServerStartFlags(flagArgs);
41432
+ function buildMergedServerEnv(entry, mode, flagEnv) {
41295
41433
  const bundledStaticClientRoot = resolveBundledStaticClientRoot(entry, mode);
41296
41434
  const autoEnv = {};
41297
41435
  if (bundledStaticClientRoot) {
@@ -41301,9 +41439,254 @@ async function runServerCommand(context, args) {
41301
41439
  autoEnv.SCOUT_STATIC_ROOT = bundledStaticClientRoot;
41302
41440
  }
41303
41441
  }
41304
- const mergedEnv = { ...process.env, ...autoEnv, ...flagEnv };
41442
+ return { ...process.env, ...autoEnv, ...flagEnv };
41443
+ }
41444
+ function parseServerSelection(args) {
41445
+ if (args[0] === "start") {
41446
+ return {
41447
+ action: "start",
41448
+ flagArgs: args.slice(1),
41449
+ entry: resolveScoutWebServerEntry(),
41450
+ mode: "full"
41451
+ };
41452
+ }
41453
+ if (args[0] === "open") {
41454
+ return {
41455
+ action: "open",
41456
+ flagArgs: args.slice(1),
41457
+ entry: resolveScoutWebServerEntry(),
41458
+ mode: "full"
41459
+ };
41460
+ }
41461
+ if (args[0] === "control-plane") {
41462
+ if (args[1] !== "start" && args[1] !== "open") {
41463
+ throw new ScoutCliError("expected: scout server control-plane <start|open>");
41464
+ }
41465
+ return {
41466
+ action: args[1],
41467
+ flagArgs: args.slice(2),
41468
+ entry: resolveScoutControlPlaneWebServerEntry(),
41469
+ mode: "control-plane"
41470
+ };
41471
+ }
41472
+ throw new ScoutCliError(`unknown subcommand: ${args[0]} (try: scout server open)`);
41473
+ }
41474
+ function normalizeServerOpenPath(value) {
41475
+ const trimmed = value.trim();
41476
+ if (!trimmed) {
41477
+ return "/";
41478
+ }
41479
+ if (trimmed.startsWith("http://") || trimmed.startsWith("https://")) {
41480
+ throw new ScoutCliError("--path must be a local path, not an absolute URL");
41481
+ }
41482
+ if (trimmed.startsWith("/")) {
41483
+ return trimmed;
41484
+ }
41485
+ return `/${trimmed}`;
41486
+ }
41487
+ function resolveServerPort(env) {
41488
+ const raw2 = env.SCOUT_WEB_PORT?.trim() || "3200";
41489
+ const port = Number.parseInt(raw2, 10);
41490
+ if (!Number.isFinite(port) || port <= 0) {
41491
+ throw new ScoutCliError(`invalid port: ${raw2}`);
41492
+ }
41493
+ return port;
41494
+ }
41495
+ function resolveExpectedCurrentDirectory(env) {
41496
+ return resolve9(env.OPENSCOUT_SETUP_CWD?.trim() || process.cwd());
41497
+ }
41498
+ function renderModeLabel(mode) {
41499
+ return mode === "control-plane" ? "Scout control plane" : "Scout";
41500
+ }
41501
+ function renderSurfaceLabel(surface) {
41502
+ switch (surface) {
41503
+ case "control-plane":
41504
+ return "control-plane";
41505
+ case "openscout-web":
41506
+ return "@openscout/web";
41507
+ case "full":
41508
+ default:
41509
+ return "full";
41510
+ }
41511
+ }
41512
+ function renderServerOpenResult(result) {
41513
+ const prefix = result.mode === "control-plane" ? "Opened Scout control plane" : "Opened Scout";
41514
+ return `${prefix} at ${result.url}${result.reusedExistingServer ? "" : " (started server)"}`;
41515
+ }
41516
+ function healthUrlForPort(port) {
41517
+ return new URL(`/api/health`, `http://127.0.0.1:${port}`);
41518
+ }
41519
+ async function probeScoutServer(port) {
41520
+ const controller = new AbortController;
41521
+ const timeout = setTimeout(() => controller.abort(), SERVER_HEALTH_TIMEOUT_MS);
41522
+ try {
41523
+ const response = await fetch(healthUrlForPort(port), {
41524
+ headers: { accept: "application/json" },
41525
+ signal: controller.signal
41526
+ });
41527
+ if (!response.ok) {
41528
+ return {
41529
+ status: "non-scout",
41530
+ statusCode: response.status
41531
+ };
41532
+ }
41533
+ let body;
41534
+ try {
41535
+ body = await response.json();
41536
+ } catch {
41537
+ return {
41538
+ status: "non-scout",
41539
+ statusCode: response.status
41540
+ };
41541
+ }
41542
+ if (body.ok === true && (body.surface === "full" || body.surface === "control-plane" || body.surface === "openscout-web") && typeof body.currentDirectory === "string") {
41543
+ return {
41544
+ status: "healthy",
41545
+ health: {
41546
+ ok: true,
41547
+ surface: body.surface,
41548
+ currentDirectory: body.currentDirectory
41549
+ }
41550
+ };
41551
+ }
41552
+ return {
41553
+ status: "non-scout",
41554
+ statusCode: response.status
41555
+ };
41556
+ } catch {
41557
+ return { status: "unreachable" };
41558
+ } finally {
41559
+ clearTimeout(timeout);
41560
+ }
41561
+ }
41562
+ async function openBrowser(url2) {
41563
+ await new Promise((resolvePromise, rejectPromise) => {
41564
+ let command;
41565
+ let args;
41566
+ if (process.platform === "darwin") {
41567
+ command = "open";
41568
+ args = [url2];
41569
+ } else if (process.platform === "win32") {
41570
+ command = "cmd";
41571
+ args = ["/c", "start", "", url2];
41572
+ } else {
41573
+ command = "xdg-open";
41574
+ args = [url2];
41575
+ }
41576
+ const child = spawn5(command, args, {
41577
+ detached: true,
41578
+ stdio: "ignore",
41579
+ windowsHide: true
41580
+ });
41581
+ child.once("error", (error48) => {
41582
+ if (error48.code === "ENOENT") {
41583
+ rejectPromise(new ScoutCliError(`could not open a browser automatically; ${command} is not available`));
41584
+ return;
41585
+ }
41586
+ rejectPromise(error48);
41587
+ });
41588
+ child.once("spawn", () => {
41589
+ child.unref();
41590
+ resolvePromise();
41591
+ });
41592
+ });
41593
+ }
41594
+ async function spawnDetachedServer(entry, env) {
41305
41595
  await new Promise((resolvePromise, rejectPromise) => {
41306
41596
  const child = spawn5("bun", ["run", entry], {
41597
+ detached: true,
41598
+ stdio: "ignore",
41599
+ env,
41600
+ windowsHide: true
41601
+ });
41602
+ child.once("error", (error48) => {
41603
+ if (error48.code === "ENOENT") {
41604
+ rejectPromise(new ScoutCliError("`bun` was not found on PATH. Install Bun (https://bun.sh) to run scout server."));
41605
+ return;
41606
+ }
41607
+ rejectPromise(error48);
41608
+ });
41609
+ child.once("spawn", () => {
41610
+ child.unref();
41611
+ resolvePromise();
41612
+ });
41613
+ });
41614
+ }
41615
+ async function waitForScoutServer(port, mode, expectedCurrentDirectory) {
41616
+ const deadline = Date.now() + SERVER_OPEN_TIMEOUT_MS;
41617
+ while (Date.now() < deadline) {
41618
+ const probe = await probeScoutServer(port);
41619
+ if (probe.status === "healthy") {
41620
+ const actualCurrentDirectory = resolve9(probe.health.currentDirectory);
41621
+ if (probe.health.surface !== mode) {
41622
+ throw new ScoutCliError(`port ${port} is serving Scout ${renderSurfaceLabel(probe.health.surface)}, not ${renderModeLabel(mode)}.`);
41623
+ }
41624
+ if (actualCurrentDirectory !== expectedCurrentDirectory) {
41625
+ throw new ScoutCliError(`port ${port} is already serving Scout for ${actualCurrentDirectory}, not ${expectedCurrentDirectory}.`);
41626
+ }
41627
+ return;
41628
+ }
41629
+ if (probe.status === "non-scout") {
41630
+ throw new ScoutCliError(`port ${port} is already serving another HTTP app or an older Scout server; choose a different --port.`);
41631
+ }
41632
+ await new Promise((resolvePromise) => setTimeout(resolvePromise, 250));
41633
+ }
41634
+ throw new ScoutCliError(`timed out waiting for ${renderModeLabel(mode)} on port ${port}`);
41635
+ }
41636
+ async function openScoutServer(options) {
41637
+ const port = resolveServerPort(options.env);
41638
+ const expectedCurrentDirectory = resolveExpectedCurrentDirectory(options.env);
41639
+ const browserUrl = new URL(normalizeServerOpenPath(options.openPath), `http://127.0.0.1:${port}`).toString();
41640
+ const probe = await probeScoutServer(port);
41641
+ if (probe.status === "healthy") {
41642
+ const actualCurrentDirectory = resolve9(probe.health.currentDirectory);
41643
+ if (probe.health.surface !== options.mode) {
41644
+ throw new ScoutCliError(`port ${port} is already serving Scout ${renderSurfaceLabel(probe.health.surface)}, not ${renderModeLabel(options.mode)}.`);
41645
+ }
41646
+ if (actualCurrentDirectory !== expectedCurrentDirectory) {
41647
+ throw new ScoutCliError(`port ${port} is already serving Scout for ${actualCurrentDirectory}, not ${expectedCurrentDirectory}.`);
41648
+ }
41649
+ await openBrowser(browserUrl);
41650
+ return {
41651
+ url: browserUrl,
41652
+ port,
41653
+ mode: options.mode,
41654
+ reusedExistingServer: true
41655
+ };
41656
+ }
41657
+ if (probe.status === "non-scout") {
41658
+ throw new ScoutCliError(`port ${port} is already serving another HTTP app or an older Scout server; choose a different --port.`);
41659
+ }
41660
+ await spawnDetachedServer(options.entry, options.env);
41661
+ await waitForScoutServer(port, options.mode, expectedCurrentDirectory);
41662
+ await openBrowser(browserUrl);
41663
+ return {
41664
+ url: browserUrl,
41665
+ port,
41666
+ mode: options.mode,
41667
+ reusedExistingServer: false
41668
+ };
41669
+ }
41670
+ async function runServerCommand(context, args) {
41671
+ if (args.length === 0 || args[0] === "help" || args[0] === "--help" || args[0] === "-h") {
41672
+ context.output.writeText(renderServerCommandHelp());
41673
+ return;
41674
+ }
41675
+ const selection = parseServerSelection(args);
41676
+ const { env: flagEnv, openPath } = parseServerFlags(selection.flagArgs);
41677
+ const mergedEnv = buildMergedServerEnv(selection.entry, selection.mode, flagEnv);
41678
+ if (selection.action === "open") {
41679
+ const result = await openScoutServer({
41680
+ entry: selection.entry,
41681
+ mode: selection.mode,
41682
+ env: mergedEnv,
41683
+ openPath
41684
+ });
41685
+ context.output.writeValue(result, renderServerOpenResult);
41686
+ return;
41687
+ }
41688
+ await new Promise((resolvePromise, rejectPromise) => {
41689
+ const child = spawn5("bun", ["run", selection.entry], {
41307
41690
  stdio: "inherit",
41308
41691
  env: mergedEnv
41309
41692
  });
@@ -41331,6 +41714,7 @@ async function runServerCommand(context, args) {
41331
41714
  });
41332
41715
  });
41333
41716
  }
41717
+ var SERVER_OPEN_TIMEOUT_MS = 15000, SERVER_HEALTH_TIMEOUT_MS = 1500;
41334
41718
  var init_server2 = __esm(() => {
41335
41719
  init_errors();
41336
41720
  });
@@ -41444,7 +41828,7 @@ import { EventEmitter } from "events";
41444
41828
  import { Buffer as Buffer2 } from "buffer";
41445
41829
  import { Buffer as Buffer3 } from "buffer";
41446
41830
  import { EventEmitter as EventEmitter2 } from "events";
41447
- import { resolve as resolve9, dirname as dirname11 } from "path";
41831
+ import { resolve as resolve10, dirname as dirname11 } from "path";
41448
41832
  import { fileURLToPath as fileURLToPath8 } from "url";
41449
41833
  import { resolve as resolve22, isAbsolute as isAbsolute5, parse as parse6 } from "path";
41450
41834
  import { existsSync as existsSync17 } from "fs";
@@ -44580,13 +44964,13 @@ class DebounceController {
44580
44964
  }
44581
44965
  debounce(id, ms, fn) {
44582
44966
  const scopeMap = TIMERS_MAP.get(this.scopeId);
44583
- return new Promise((resolve11, reject) => {
44967
+ return new Promise((resolve12, reject) => {
44584
44968
  if (scopeMap.has(id)) {
44585
44969
  clearTimeout(scopeMap.get(id));
44586
44970
  }
44587
44971
  const timerId = setTimeout(() => {
44588
44972
  try {
44589
- resolve11(fn());
44973
+ resolve12(fn());
44590
44974
  } catch (error48) {
44591
44975
  reject(error48);
44592
44976
  }
@@ -44676,25 +45060,25 @@ function getParsers() {
44676
45060
  filetype: "javascript",
44677
45061
  aliases: ["javascriptreact"],
44678
45062
  queries: {
44679
- highlights: [resolve9(dirname11(fileURLToPath8(import.meta.url)), highlights_default)]
45063
+ highlights: [resolve10(dirname11(fileURLToPath8(import.meta.url)), highlights_default)]
44680
45064
  },
44681
- wasm: resolve9(dirname11(fileURLToPath8(import.meta.url)), tree_sitter_javascript_default)
45065
+ wasm: resolve10(dirname11(fileURLToPath8(import.meta.url)), tree_sitter_javascript_default)
44682
45066
  },
44683
45067
  {
44684
45068
  filetype: "typescript",
44685
45069
  aliases: ["typescriptreact"],
44686
45070
  queries: {
44687
- highlights: [resolve9(dirname11(fileURLToPath8(import.meta.url)), highlights_default2)]
45071
+ highlights: [resolve10(dirname11(fileURLToPath8(import.meta.url)), highlights_default2)]
44688
45072
  },
44689
- wasm: resolve9(dirname11(fileURLToPath8(import.meta.url)), tree_sitter_typescript_default)
45073
+ wasm: resolve10(dirname11(fileURLToPath8(import.meta.url)), tree_sitter_typescript_default)
44690
45074
  },
44691
45075
  {
44692
45076
  filetype: "markdown",
44693
45077
  queries: {
44694
- highlights: [resolve9(dirname11(fileURLToPath8(import.meta.url)), highlights_default3)],
44695
- injections: [resolve9(dirname11(fileURLToPath8(import.meta.url)), injections_default)]
45078
+ highlights: [resolve10(dirname11(fileURLToPath8(import.meta.url)), highlights_default3)],
45079
+ injections: [resolve10(dirname11(fileURLToPath8(import.meta.url)), injections_default)]
44696
45080
  },
44697
- wasm: resolve9(dirname11(fileURLToPath8(import.meta.url)), tree_sitter_markdown_default),
45081
+ wasm: resolve10(dirname11(fileURLToPath8(import.meta.url)), tree_sitter_markdown_default),
44698
45082
  injectionMapping: {
44699
45083
  nodeTypes: {
44700
45084
  inline: "markdown_inline",
@@ -44717,16 +45101,16 @@ function getParsers() {
44717
45101
  {
44718
45102
  filetype: "markdown_inline",
44719
45103
  queries: {
44720
- highlights: [resolve9(dirname11(fileURLToPath8(import.meta.url)), highlights_default4)]
45104
+ highlights: [resolve10(dirname11(fileURLToPath8(import.meta.url)), highlights_default4)]
44721
45105
  },
44722
- wasm: resolve9(dirname11(fileURLToPath8(import.meta.url)), tree_sitter_markdown_inline_default)
45106
+ wasm: resolve10(dirname11(fileURLToPath8(import.meta.url)), tree_sitter_markdown_inline_default)
44723
45107
  },
44724
45108
  {
44725
45109
  filetype: "zig",
44726
45110
  queries: {
44727
- highlights: [resolve9(dirname11(fileURLToPath8(import.meta.url)), highlights_default5)]
45111
+ highlights: [resolve10(dirname11(fileURLToPath8(import.meta.url)), highlights_default5)]
44728
45112
  },
44729
- wasm: resolve9(dirname11(fileURLToPath8(import.meta.url)), tree_sitter_zig_default)
45113
+ wasm: resolve10(dirname11(fileURLToPath8(import.meta.url)), tree_sitter_zig_default)
44730
45114
  }
44731
45115
  ];
44732
45116
  }
@@ -73962,14 +74346,14 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
73962
74346
  prevActScopeDepth !== actScopeDepth - 1 && console.error("You seem to have overlapping act() calls, this is not supported. Be sure to await previous act() calls before making a new one. ");
73963
74347
  actScopeDepth = prevActScopeDepth;
73964
74348
  }
73965
- function recursivelyFlushAsyncActWork(returnValue, resolve11, reject) {
74349
+ function recursivelyFlushAsyncActWork(returnValue, resolve12, reject) {
73966
74350
  var queue = ReactSharedInternals.actQueue;
73967
74351
  if (queue !== null)
73968
74352
  if (queue.length !== 0)
73969
74353
  try {
73970
74354
  flushActQueue(queue);
73971
74355
  enqueueTask(function() {
73972
- return recursivelyFlushAsyncActWork(returnValue, resolve11, reject);
74356
+ return recursivelyFlushAsyncActWork(returnValue, resolve12, reject);
73973
74357
  });
73974
74358
  return;
73975
74359
  } catch (error48) {
@@ -73977,7 +74361,7 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
73977
74361
  }
73978
74362
  else
73979
74363
  ReactSharedInternals.actQueue = null;
73980
- 0 < ReactSharedInternals.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(queue)) : resolve11(returnValue);
74364
+ 0 < ReactSharedInternals.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(queue)) : resolve12(returnValue);
73981
74365
  }
73982
74366
  function flushActQueue(queue) {
73983
74367
  if (!isFlushing) {
@@ -74153,14 +74537,14 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
74153
74537
  didAwaitActCall || didWarnNoAwaitAct || (didWarnNoAwaitAct = true, console.error("You called act(async () => ...) without await. This could lead to unexpected testing behaviour, interleaving multiple act calls and mixing their scopes. You should - await act(async () => ...);"));
74154
74538
  });
74155
74539
  return {
74156
- then: function(resolve11, reject) {
74540
+ then: function(resolve12, reject) {
74157
74541
  didAwaitActCall = true;
74158
74542
  thenable.then(function(returnValue) {
74159
74543
  popActScope(prevActQueue, prevActScopeDepth);
74160
74544
  if (prevActScopeDepth === 0) {
74161
74545
  try {
74162
74546
  flushActQueue(queue), enqueueTask(function() {
74163
- return recursivelyFlushAsyncActWork(returnValue, resolve11, reject);
74547
+ return recursivelyFlushAsyncActWork(returnValue, resolve12, reject);
74164
74548
  });
74165
74549
  } catch (error$0) {
74166
74550
  ReactSharedInternals.thrownErrors.push(error$0);
@@ -74171,7 +74555,7 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
74171
74555
  reject(_thrownError);
74172
74556
  }
74173
74557
  } else
74174
- resolve11(returnValue);
74558
+ resolve12(returnValue);
74175
74559
  }, function(error48) {
74176
74560
  popActScope(prevActQueue, prevActScopeDepth);
74177
74561
  0 < ReactSharedInternals.thrownErrors.length ? (error48 = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(error48)) : reject(error48);
@@ -74187,11 +74571,11 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
74187
74571
  if (0 < ReactSharedInternals.thrownErrors.length)
74188
74572
  throw callback = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, callback;
74189
74573
  return {
74190
- then: function(resolve11, reject) {
74574
+ then: function(resolve12, reject) {
74191
74575
  didAwaitActCall = true;
74192
74576
  prevActScopeDepth === 0 ? (ReactSharedInternals.actQueue = queue, enqueueTask(function() {
74193
- return recursivelyFlushAsyncActWork(returnValue$jscomp$0, resolve11, reject);
74194
- })) : resolve11(returnValue$jscomp$0);
74577
+ return recursivelyFlushAsyncActWork(returnValue$jscomp$0, resolve12, reject);
74578
+ })) : resolve12(returnValue$jscomp$0);
74195
74579
  }
74196
74580
  };
74197
74581
  };
@@ -76672,8 +77056,8 @@ It can also happen if the client has a browser extension installed which messes
76672
77056
  currentEntangledActionThenable = {
76673
77057
  status: "pending",
76674
77058
  value: undefined,
76675
- then: function(resolve11) {
76676
- entangledListeners.push(resolve11);
77059
+ then: function(resolve12) {
77060
+ entangledListeners.push(resolve12);
76677
77061
  }
76678
77062
  };
76679
77063
  }
@@ -76697,8 +77081,8 @@ It can also happen if the client has a browser extension installed which messes
76697
77081
  status: "pending",
76698
77082
  value: null,
76699
77083
  reason: null,
76700
- then: function(resolve11) {
76701
- listeners.push(resolve11);
77084
+ then: function(resolve12) {
77085
+ listeners.push(resolve12);
76702
77086
  }
76703
77087
  };
76704
77088
  thenable.then(function() {
@@ -102680,14 +103064,14 @@ async function runScoutMonitorApp(options) {
102680
103064
  }
102681
103065
  const renderer = await createCliRenderer();
102682
103066
  let closed = false;
102683
- await new Promise((resolve11) => {
103067
+ await new Promise((resolve12) => {
102684
103068
  const close = () => {
102685
103069
  if (closed) {
102686
103070
  return;
102687
103071
  }
102688
103072
  closed = true;
102689
103073
  renderer.destroy();
102690
- resolve11();
103074
+ resolve12();
102691
103075
  };
102692
103076
  createRoot(renderer).render(/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ScoutMonitorApp, {
102693
103077
  currentDirectory: options.currentDirectory,
@@ -102736,7 +103120,7 @@ __export(exports_up, {
102736
103120
  runUpCommand: () => runUpCommand
102737
103121
  });
102738
103122
  import { existsSync as existsSync18 } from "fs";
102739
- import { resolve as resolve11 } from "path";
103123
+ import { resolve as resolve12 } from "path";
102740
103124
  function looksLikePath(value) {
102741
103125
  return value.includes("/") || value.startsWith(".") || value.startsWith("~");
102742
103126
  }
@@ -102784,8 +103168,8 @@ async function runUpCommand(context, args) {
102784
103168
  throw new ScoutCliError("usage: scout up <name|path> [--name <alias>] [--harness <claude|codex>]");
102785
103169
  }
102786
103170
  let projectPath;
102787
- if (looksLikePath(target) || existsSync18(resolve11(target))) {
102788
- projectPath = resolve11(target);
103171
+ if (looksLikePath(target) || existsSync18(resolve12(target))) {
103172
+ projectPath = resolve12(target);
102789
103173
  } else {
102790
103174
  const resolved = await resolveLocalAgentByName(target);
102791
103175
  if (!resolved) {
@@ -102861,6 +103245,52 @@ var init_who = __esm(async () => {
102861
103245
  await init_service();
102862
103246
  });
102863
103247
 
103248
+ // ../../apps/desktop/src/cli/commands/whoami.ts
103249
+ var exports_whoami = {};
103250
+ __export(exports_whoami, {
103251
+ runWhoAmICommand: () => runWhoAmICommand
103252
+ });
103253
+ async function loadScoutWhoAmIReport(context, currentDirectory) {
103254
+ const askWatchId = resolveScoutAgentName(null);
103255
+ const sendSpeakId = await resolveScoutSenderId(null, currentDirectory);
103256
+ const projectRoot = await findNearestProjectRoot(currentDirectory);
103257
+ return {
103258
+ askWatchId,
103259
+ sendSpeakId,
103260
+ envAgent: context.env.OPENSCOUT_AGENT?.trim() || null,
103261
+ currentDirectory,
103262
+ projectRoot,
103263
+ brokerUrl: resolveScoutBrokerUrl()
103264
+ };
103265
+ }
103266
+ function renderScoutWhoAmIReport(report) {
103267
+ const lines = [
103268
+ `Ask/Watch: ${report.askWatchId}`,
103269
+ `Send/Speak: ${report.sendSpeakId}`,
103270
+ `Current Directory: ${report.currentDirectory}`,
103271
+ `Broker: ${report.brokerUrl}`
103272
+ ];
103273
+ if (report.projectRoot) {
103274
+ lines.splice(3, 0, `Project Root: ${report.projectRoot}`);
103275
+ }
103276
+ if (report.envAgent) {
103277
+ lines.splice(2, 0, `OPENSCOUT_AGENT: ${report.envAgent}`);
103278
+ }
103279
+ return lines.join(`
103280
+ `);
103281
+ }
103282
+ async function runWhoAmICommand(context, args) {
103283
+ const options = parseContextRootCommandOptions("whoami", args, defaultScoutContextDirectory(context));
103284
+ const report = await loadScoutWhoAmIReport(context, options.currentDirectory);
103285
+ context.output.writeValue(report, renderScoutWhoAmIReport);
103286
+ }
103287
+ var init_whoami = __esm(async () => {
103288
+ init_setup();
103289
+ init_context();
103290
+ init_options();
103291
+ await init_service();
103292
+ });
103293
+
102864
103294
  // ../../apps/desktop/src/cli/argv.ts
102865
103295
  function parseScoutArgv(argv) {
102866
103296
  let command = null;
@@ -102920,6 +103350,8 @@ async function loadScoutCommandHandler(name) {
102920
103350
  return (await init_enroll().then(() => exports_enroll)).runEnrollCommand;
102921
103351
  case "env":
102922
103352
  return (await init_env().then(() => exports_env)).runEnvCommand;
103353
+ case "latest":
103354
+ return (await init_latest().then(() => exports_latest)).runLatestCommand;
102923
103355
  case "mesh":
102924
103356
  return (await init_mesh().then(() => exports_mesh)).runMeshCommand;
102925
103357
  case "pair":
@@ -102946,6 +103378,8 @@ async function loadScoutCommandHandler(name) {
102946
103378
  return (await init_watch().then(() => exports_watch)).runWatchCommand;
102947
103379
  case "who":
102948
103380
  return (await init_who().then(() => exports_who)).runWhoCommand;
103381
+ case "whoami":
103382
+ return (await init_whoami().then(() => exports_whoami)).runWhoAmICommand;
102949
103383
  }
102950
103384
  }
102951
103385
 
@@ -102957,12 +103391,14 @@ var SCOUT_COMMANDS = [
102957
103391
  { name: "doctor", summary: "Show broker health and project inventory" },
102958
103392
  { name: "runtimes", summary: "Show harness catalog and readiness" },
102959
103393
  { name: "env", summary: "Show executable and agent identity context" },
103394
+ { name: "whoami", summary: "Show your current Scout identity defaults" },
102960
103395
  { name: "send", summary: "Post a broker-backed message" },
102961
103396
  { name: "speak", summary: "Send and speak aloud via TTS" },
102962
103397
  { name: "ask", summary: "Ask an agent and wait for the answer" },
102963
103398
  { name: "card", summary: "Create a dedicated relay agent card" },
102964
103399
  { name: "watch", summary: "Stream broker messages" },
102965
103400
  { name: "who", summary: "List agents and last activity" },
103401
+ { name: "latest", summary: "Show the latest Scout activity" },
102966
103402
  { name: "enroll", summary: "Generate enrollment prompt" },
102967
103403
  { name: "broadcast", summary: "Send to all routable agents" },
102968
103404
  { name: "up", summary: "Spawn a local agent for a project" },
@@ -103021,6 +103457,12 @@ function renderScoutHelp(version2 = "0.2.18") {
103021
103457
  " scout hey @agent can you review this?",
103022
103458
  " scout @agent.harness:codex use the Codex-backed one",
103023
103459
  "",
103460
+ "Operator loop:",
103461
+ " scout whoami",
103462
+ " scout who",
103463
+ " scout latest",
103464
+ " scout server open",
103465
+ "",
103024
103466
  "Addressing:",
103025
103467
  " @name short form; requires exactly one live match",
103026
103468
  " @name.harness:<codex|claude|...> pin a specific harness (alias: runtime:)",