@openscout/scout 0.2.109 → 0.2.110

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.
@@ -14399,7 +14399,7 @@ var require_cjs11 = __commonJS((exports) => {
14399
14399
  import { spawn as spawn2, spawnSync } from "node:child_process";
14400
14400
  import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync5, renameSync as renameSync3, writeFileSync as writeFileSync4 } from "node:fs";
14401
14401
  import { homedir as homedir5, networkInterfaces } from "node:os";
14402
- import { basename as basename2, dirname as dirname4, join as join6, resolve as resolve2 } from "node:path";
14402
+ import { basename as basename2, dirname as dirname5, join as join6, resolve as resolve2 } from "node:path";
14403
14403
  import { fileURLToPath } from "node:url";
14404
14404
 
14405
14405
  // ../runtime/dist/broker-api.js
@@ -14565,6 +14565,15 @@ async function requestBrokerWire(baseUrl, path, options) {
14565
14565
  }
14566
14566
  };
14567
14567
  }
14568
+
14569
+ class ScoutBrokerHttpError extends Error {
14570
+ status;
14571
+ constructor(status, path, body) {
14572
+ super(`${path} returned ${status}: ${body}`);
14573
+ this.status = status;
14574
+ this.name = "ScoutBrokerHttpError";
14575
+ }
14576
+ }
14568
14577
  async function requestScoutBrokerJsonWithTrace(baseUrl, path, options = {}) {
14569
14578
  const { response, trace } = await requestBrokerWire(baseUrl, path, options);
14570
14579
  let parsed;
@@ -14581,7 +14590,7 @@ async function requestScoutBrokerJsonWithTrace(baseUrl, path, options = {}) {
14581
14590
  if (parsedJson && options.acceptErrorJson?.(parsed)) {
14582
14591
  return { value: parsed, trace };
14583
14592
  }
14584
- throw new Error(`${path} returned ${response.status}: ${response.text}`);
14593
+ throw new ScoutBrokerHttpError(response.status, path, response.text);
14585
14594
  }
14586
14595
  if (parsedJson) {
14587
14596
  return { value: parsed, trace };
@@ -14854,7 +14863,7 @@ class NodeSqliteDatabaseAdapter {
14854
14863
  // ../runtime/dist/support-paths.js
14855
14864
  import { existsSync as existsSync2, mkdirSync, rmSync, writeFileSync } from "node:fs";
14856
14865
  import { homedir } from "node:os";
14857
- import { join } from "node:path";
14866
+ import { dirname, join } from "node:path";
14858
14867
  var OPENSCOUT_RPC_CUTOVER_MARKER = "rpc-runtime-cutover-v1";
14859
14868
  function isTestRunnerProcess() {
14860
14869
  if (false)
@@ -14869,9 +14878,16 @@ function assertTestIsolatedUserData(operation, isolationEnvKey) {
14869
14878
  return;
14870
14879
  throw new Error(`Refusing to ${operation} under a test runner without ${isolationEnvKey} set. ` + "Tests must isolate OpenScout user data in a temp directory (see prepareHome in onboarding.test.ts).");
14871
14880
  }
14881
+ function defaultOpenScoutSupportDirectory(home = homedir()) {
14882
+ if (process.platform === "darwin") {
14883
+ return join(home, "Library", "Application Support", "OpenScout");
14884
+ }
14885
+ const xdgDataHome = process.env.XDG_DATA_HOME?.trim();
14886
+ return join(xdgDataHome || join(home, ".local", "share"), "openscout");
14887
+ }
14872
14888
  function resolveOpenScoutSupportPaths() {
14873
14889
  const home = homedir();
14874
- const supportDirectory = process.env.OPENSCOUT_SUPPORT_DIRECTORY ?? join(home, "Library", "Application Support", "OpenScout");
14890
+ const supportDirectory = process.env.OPENSCOUT_SUPPORT_DIRECTORY ?? defaultOpenScoutSupportDirectory(home);
14875
14891
  const logsDirectory = join(supportDirectory, "logs");
14876
14892
  const runtimeDirectory = join(supportDirectory, "runtime");
14877
14893
  const catalogDirectory = join(supportDirectory, "catalog");
@@ -16321,12 +16337,12 @@ function readTailscaleSelfWebHostsSync(env = process.env) {
16321
16337
  // ../runtime/dist/local-config.js
16322
16338
  import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "node:fs";
16323
16339
  import { homedir as homedir3, hostname as osHostname } from "node:os";
16324
- import { dirname as dirname2, join as join4 } from "node:path";
16340
+ import { dirname as dirname3, join as join4 } from "node:path";
16325
16341
 
16326
16342
  // ../runtime/dist/node-identity.js
16327
16343
  import { createHash as createHash2, createPrivateKey, createPublicKey, generateKeyPairSync, randomBytes, sign, verify } from "node:crypto";
16328
16344
  import { chmodSync, existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync3, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
16329
- import { dirname, join as join3 } from "node:path";
16345
+ import { dirname as dirname2, join as join3 } from "node:path";
16330
16346
  var NODE_IDENTITY_FILE = "node-identity.json";
16331
16347
  var NODE_FINGERPRINT_PREFIX = "osc1";
16332
16348
  var NODE_CARD_TTL_MS = 24 * 60 * 60 * 1000;
@@ -16425,7 +16441,7 @@ function createNodeIdentity(supportDirectory) {
16425
16441
  privateKey: privateKey.export({ type: "pkcs8", format: "der" }).toString("base64"),
16426
16442
  createdAt: Date.now()
16427
16443
  };
16428
- mkdirSync2(dirname(path), { recursive: true });
16444
+ mkdirSync2(dirname2(path), { recursive: true });
16429
16445
  try {
16430
16446
  writeFileSync2(path, `${JSON.stringify(identity, null, 2)}
16431
16447
  `, { encoding: "utf8", mode: 384, flag: "wx" });
@@ -16632,7 +16648,7 @@ function resolveBrokerPort() {
16632
16648
  function writeLocalConfig(config) {
16633
16649
  assertTestIsolatedUserData("write the OpenScout local config", "OPENSCOUT_HOME");
16634
16650
  const configPath = localConfigPath();
16635
- mkdirSync3(dirname2(configPath), { recursive: true });
16651
+ mkdirSync3(dirname3(configPath), { recursive: true });
16636
16652
  const body = JSON.stringify({ ...config, version: LOCAL_CONFIG_VERSION }, null, 2) + `
16637
16653
  `;
16638
16654
  const tmp = `${configPath}.tmp`;
@@ -16646,7 +16662,7 @@ function localConfigExists() {
16646
16662
  // ../runtime/dist/tool-resolution.js
16647
16663
  import { accessSync, constants, existsSync as existsSync6 } from "node:fs";
16648
16664
  import { homedir as homedir4 } from "node:os";
16649
- import { basename, dirname as dirname3, join as join5, resolve } from "node:path";
16665
+ import { basename, dirname as dirname4, join as join5, resolve } from "node:path";
16650
16666
  var DEFAULT_COMMON_EXECUTABLE_DIRECTORIES = [
16651
16667
  join5(homedir4(), ".bun", "bin"),
16652
16668
  "/opt/homebrew/bin",
@@ -16940,7 +16956,7 @@ function runtimePackageDir() {
16940
16956
  const fromGlobal = findGlobalRuntimeDir();
16941
16957
  if (fromGlobal)
16942
16958
  return fromGlobal;
16943
- const moduleDir = dirname4(fileURLToPath(import.meta.url));
16959
+ const moduleDir = dirname5(fileURLToPath(import.meta.url));
16944
16960
  return resolve2(moduleDir, "..");
16945
16961
  }
16946
16962
  function isInstalledRuntimePackageDir(candidate) {
@@ -16974,7 +16990,7 @@ function findGlobalRuntimeDir() {
16974
16990
  return null;
16975
16991
  }
16976
16992
  function findBundledRuntimeDir() {
16977
- const moduleDir = dirname4(fileURLToPath(import.meta.url));
16993
+ const moduleDir = dirname5(fileURLToPath(import.meta.url));
16978
16994
  return resolveBundledRuntimeDirFromModuleDir(moduleDir);
16979
16995
  }
16980
16996
  function resolveBundledRuntimeDirFromModuleDir(moduleDir) {
@@ -16993,7 +17009,7 @@ function resolveBundledRuntimeDirFromModuleDir(moduleDir) {
16993
17009
  return null;
16994
17010
  }
16995
17011
  function resolveSourceWorkspaceRuntimeDir(bundledPackageDir) {
16996
- const packagesDir = dirname4(bundledPackageDir);
17012
+ const packagesDir = dirname5(bundledPackageDir);
16997
17013
  if (resolve2(packagesDir, "cli") !== resolve2(bundledPackageDir))
16998
17014
  return null;
16999
17015
  const runtimeDir = join6(packagesDir, "runtime");
@@ -17016,7 +17032,7 @@ function findWorkspaceRuntimeDir(startDir) {
17016
17032
  if (existsSync7(join6(candidate, "package.json")) && existsSync7(join6(candidate, "src"))) {
17017
17033
  return candidate;
17018
17034
  }
17019
- const parent = dirname4(current);
17035
+ const parent = dirname5(current);
17020
17036
  if (parent === current)
17021
17037
  return null;
17022
17038
  current = parent;
@@ -17063,7 +17079,7 @@ function resolveBrokerServiceConfig() {
17063
17079
  const serviceAdapter = resolveBrokerServiceAdapter();
17064
17080
  const uid = typeof process.getuid === "function" ? process.getuid() : Number.parseInt(process.env.UID ?? "0", 10);
17065
17081
  const supportPaths = resolveOpenScoutSupportPaths();
17066
- const defaultSupportDir = join6(homedir5(), "Library", "Application Support", "OpenScout");
17082
+ const defaultSupportDir = defaultOpenScoutSupportDirectory();
17067
17083
  const supportDirectory = isTmpPath(supportPaths.supportDirectory) ? defaultSupportDir : supportPaths.supportDirectory;
17068
17084
  const runtimeDirectory = join6(supportDirectory, "runtime");
17069
17085
  const logsDirectory = join6(supportDirectory, "logs", "broker");
@@ -17122,7 +17138,7 @@ function findWorkspaceRootFromRuntimeDir(runtimePackageDir2) {
17122
17138
  if (existsSync7(join6(current, "Cargo.toml")) && existsSync7(join6(current, "crates", "scoutd", "Cargo.toml"))) {
17123
17139
  return current;
17124
17140
  }
17125
- const parent = dirname4(current);
17141
+ const parent = dirname5(current);
17126
17142
  if (parent === current)
17127
17143
  return null;
17128
17144
  current = parent;
@@ -17132,7 +17148,12 @@ function workspaceScoutdAllowed() {
17132
17148
  const raw = process.env.OPENSCOUT_ALLOW_WORKSPACE_SCOUTD?.trim().toLowerCase();
17133
17149
  return raw === "1" || raw === "true" || raw === "yes" || raw === "on";
17134
17150
  }
17151
+ function nativeSupervisorNotApplicableDetail(platform = process.platform) {
17152
+ return platform === "linux" ? "native supervisor: not applicable on linux" : `native supervisor: not applicable on ${platform}`;
17153
+ }
17135
17154
  function resolveScoutdCommand(config = resolveBrokerServiceConfig()) {
17155
+ if (process.platform !== "darwin")
17156
+ return null;
17136
17157
  const explicit = resolveEnvExecutable(process.env.OPENSCOUT_SCOUTD_BIN);
17137
17158
  if (explicit) {
17138
17159
  return { path: explicit, source: "env" };
@@ -17145,7 +17166,7 @@ function resolveScoutdCommand(config = resolveBrokerServiceConfig()) {
17145
17166
  workspaceRoot ? join6(workspaceRoot, "packages", "cli", "bin", "scoutd") : null,
17146
17167
  workspaceRoot ? join6(workspaceRoot, "packages", "runtime", "bin", "scoutd") : null,
17147
17168
  join6(config.runtimeDirectory, "scoutd"),
17148
- join6(dirname4(config.runtimePackageDir), "scout", "bin", "scoutd")
17169
+ join6(dirname5(config.runtimePackageDir), "scout", "bin", "scoutd")
17149
17170
  ];
17150
17171
  for (const candidate of packageCandidates) {
17151
17172
  const resolved = executableCandidate(candidate);
@@ -17275,6 +17296,8 @@ function normalizeNativeServiceStatus(input, config) {
17275
17296
  reachable: healthReachable,
17276
17297
  ok: healthOk,
17277
17298
  checkedAt: readNumber2(healthRecord.checkedAt) ?? Date.now(),
17299
+ state: readString2(healthRecord.state),
17300
+ durationMs: readNumber2(healthRecord.durationMs),
17278
17301
  transport: healthTransport,
17279
17302
  socketPath: config.brokerSocketPath,
17280
17303
  ...healthSocketFallbackError ? { socketFallbackError: healthSocketFallbackError } : {},
@@ -17386,6 +17409,9 @@ async function runScoutdServiceCommand(command, config, timeoutMs = SCOUTD_DEFAU
17386
17409
  }
17387
17410
  const scoutd = resolveScoutdCommand(config);
17388
17411
  if (!scoutd) {
17412
+ if (process.platform !== "darwin") {
17413
+ throw new Error(nativeSupervisorNotApplicableDetail());
17414
+ }
17389
17415
  throw new Error("Unable to locate scoutd for broker service management. Build scoutd with `npm run scoutd:build`, install a package that includes scoutd, or set OPENSCOUT_SCOUTD_BIN.");
17390
17416
  }
17391
17417
  const stdout = await runScoutdJson(scoutd.path, command, nativeServiceEnvironment(config, scoutd.path), timeoutMs);
@@ -17649,7 +17675,7 @@ import { execFileSync as execFileSync3 } from "node:child_process";
17649
17675
  import { existsSync as existsSync8, statSync } from "node:fs";
17650
17676
  import { mkdir, readFile as readFile2, writeFile } from "node:fs/promises";
17651
17677
  import { homedir as homedir6 } from "node:os";
17652
- import { dirname as dirname5, join as join8 } from "node:path";
17678
+ import { dirname as dirname6, join as join8 } from "node:path";
17653
17679
 
17654
17680
  // ../agent-sessions/dist/codex-executable.js
17655
17681
  import { execFileSync as execFileSync2 } from "node:child_process";
@@ -18229,7 +18255,7 @@ var BUILT_IN_HARNESS_CATALOG = [
18229
18255
  {
18230
18256
  name: "opencode",
18231
18257
  harness: "opencode",
18232
- aliases: ["oc", "opencode2"],
18258
+ aliases: ["oc"],
18233
18259
  label: "OpenCode",
18234
18260
  description: "OpenCode's coding agent over ACP, fronting many model vendors via OpenCode Zen",
18235
18261
  homepage: "https://opencode.ai/docs/",
@@ -18676,7 +18702,7 @@ async function readHarnessCatalogOverrides(overridePath = resolveOpenScoutSuppor
18676
18702
  }
18677
18703
  }
18678
18704
  async function writeHarnessCatalogOverrides(overrides, overridePath = resolveOpenScoutSupportPaths().harnessCatalogPath) {
18679
- await mkdir(dirname5(overridePath), { recursive: true });
18705
+ await mkdir(dirname6(overridePath), { recursive: true });
18680
18706
  const payload = {
18681
18707
  version: HARNESS_CATALOG_VERSION,
18682
18708
  entries: overrides,
@@ -18710,14 +18736,14 @@ async function loadHarnessCatalogSnapshot(options = {}) {
18710
18736
  // ../runtime/dist/onboarding.js
18711
18737
  import { existsSync as existsSync11 } from "node:fs";
18712
18738
  import { homedir as homedir10 } from "node:os";
18713
- import { dirname as dirname11, join as join13, resolve as resolve5 } from "node:path";
18739
+ import { dirname as dirname12, join as join13, resolve as resolve5 } from "node:path";
18714
18740
 
18715
18741
  // ../runtime/dist/setup.js
18716
18742
  import { execFileSync as execFileSync4 } from "node:child_process";
18717
18743
  import { existsSync as existsSync9, readFileSync as readFileSync6 } from "node:fs";
18718
18744
  import { access, chmod, mkdir as mkdir4, readdir as readdir2, readFile as readFile6, realpath, rm, stat as stat2, writeFile as writeFile4 } from "node:fs/promises";
18719
18745
  import { homedir as homedir8, hostname, userInfo } from "node:os";
18720
- import { basename as basename4, dirname as dirname9, isAbsolute, join as join11, relative, resolve as resolve4 } from "node:path";
18746
+ import { basename as basename4, dirname as dirname10, isAbsolute, join as join11, relative, resolve as resolve4 } from "node:path";
18721
18747
  import { fileURLToPath as fileURLToPath3 } from "node:url";
18722
18748
 
18723
18749
  // ../../node_modules/.bun/smol-toml@1.6.1/node_modules/smol-toml/dist/error.js
@@ -20175,39 +20201,10 @@ function assertValidCollaborationEvent(event, record) {
20175
20201
  }
20176
20202
  }
20177
20203
 
20178
- // ../protocol/dist/permission-policy.js
20179
- var SCOUT_PERMISSION_PROFILES = [
20180
- "observe",
20181
- "review",
20182
- "workspace_write",
20183
- "sandboxed_write",
20184
- "trusted_local",
20185
- "external_sandbox"
20186
- ];
20187
- function normalizeScoutPermissionProfile(value) {
20188
- const normalized = value?.trim().replaceAll("-", "_");
20189
- return SCOUT_PERMISSION_PROFILES.find((profile) => profile === normalized);
20190
- }
20191
-
20192
- // ../protocol/dist/presence.js
20193
- var PRESENCE_STALE_AFTER_MS = 45000;
20194
- var PRESENCE_GONE_AFTER_STALE_MS = 60000;
20195
- function presenceLifecycle(beat, now, options = {}) {
20196
- if (now < beat.staleAt)
20197
- return "fresh";
20198
- const goneAfterStaleMs = options.goneAfterStaleMs ?? PRESENCE_GONE_AFTER_STALE_MS;
20199
- if (now < beat.staleAt + goneAfterStaleMs)
20200
- return "stale";
20201
- return "gone";
20202
- }
20203
- function isPresenceGone(beat, now, options = {}) {
20204
- return presenceLifecycle(beat, now, options) === "gone";
20205
- }
20206
-
20207
20204
  // ../protocol/dist/runtime-catalog.generated.js
20208
20205
  var SCOUT_RUNTIME_CATALOG_DATA = {
20209
20206
  schemaVersion: "openscout.runtime-catalog.v1",
20210
- revision: "2026-09-14.1",
20207
+ revision: "2026-09-24.1",
20211
20208
  harnesses: [
20212
20209
  {
20213
20210
  id: "claude",
@@ -20222,14 +20219,32 @@ var SCOUT_RUNTIME_CATALOG_DATA = {
20222
20219
  "max"
20223
20220
  ],
20224
20221
  defaultReasoningEffort: "medium",
20222
+ presentation: {
20223
+ short: "Claude",
20224
+ monogram: "✳"
20225
+ },
20225
20226
  models: [
20227
+ {
20228
+ id: "claude-opus-5-5",
20229
+ label: "Opus 5.5",
20230
+ enabled: true,
20231
+ default: true,
20232
+ family: "Opus",
20233
+ version: "5.5",
20234
+ contextWindowTokens: 1e6,
20235
+ presentation: {
20236
+ detail: "Latest"
20237
+ }
20238
+ },
20226
20239
  {
20227
20240
  id: "claude-opus-5",
20228
20241
  label: "Opus 5",
20229
20242
  enabled: true,
20230
- default: true,
20231
20243
  family: "Opus",
20232
- version: "5"
20244
+ version: "5",
20245
+ presentation: {
20246
+ detail: "Deepest"
20247
+ }
20233
20248
  },
20234
20249
  {
20235
20250
  id: "claude-fable-5",
@@ -20243,14 +20258,20 @@ var SCOUT_RUNTIME_CATALOG_DATA = {
20243
20258
  label: "Sonnet 4.6",
20244
20259
  enabled: true,
20245
20260
  family: "Sonnet",
20246
- version: "4.6"
20261
+ version: "4.6",
20262
+ presentation: {
20263
+ detail: "Balanced"
20264
+ }
20247
20265
  },
20248
20266
  {
20249
20267
  id: "claude-haiku-4-5",
20250
20268
  label: "Haiku 4.5",
20251
20269
  enabled: true,
20252
20270
  family: "Haiku",
20253
- version: "4.5"
20271
+ version: "4.5",
20272
+ presentation: {
20273
+ detail: "Fast"
20274
+ }
20254
20275
  },
20255
20276
  {
20256
20277
  id: "claude-opus-4-8",
@@ -20286,6 +20307,10 @@ var SCOUT_RUNTIME_CATALOG_DATA = {
20286
20307
  "xhigh"
20287
20308
  ],
20288
20309
  defaultReasoningEffort: "medium",
20310
+ presentation: {
20311
+ short: "Codex",
20312
+ monogram: "◈"
20313
+ },
20289
20314
  models: [
20290
20315
  {
20291
20316
  id: "gpt-6-astra",
@@ -20302,7 +20327,50 @@ var SCOUT_RUNTIME_CATALOG_DATA = {
20302
20327
  "high",
20303
20328
  "xhigh",
20304
20329
  "max"
20305
- ]
20330
+ ],
20331
+ defaultReasoningEffort: "low",
20332
+ presentation: {
20333
+ detail: "Most capable"
20334
+ }
20335
+ },
20336
+ {
20337
+ id: "gpt-6-sol",
20338
+ label: "6 Sol",
20339
+ enabled: true,
20340
+ description: "Complex coding and agentic workflows",
20341
+ family: "GPT",
20342
+ version: "6 Sol",
20343
+ contextWindowTokens: 272000,
20344
+ reasoningEfforts: [
20345
+ "low",
20346
+ "medium",
20347
+ "high",
20348
+ "xhigh",
20349
+ "max",
20350
+ "ultra"
20351
+ ],
20352
+ presentation: {
20353
+ detail: "Coding"
20354
+ }
20355
+ },
20356
+ {
20357
+ id: "gpt-6-luna",
20358
+ label: "6 Luna",
20359
+ enabled: true,
20360
+ description: "Efficient focused coding and repeatable tasks",
20361
+ family: "GPT",
20362
+ version: "6 Luna",
20363
+ contextWindowTokens: 272000,
20364
+ reasoningEfforts: [
20365
+ "low",
20366
+ "medium",
20367
+ "high",
20368
+ "xhigh",
20369
+ "max"
20370
+ ],
20371
+ presentation: {
20372
+ detail: "Efficient"
20373
+ }
20306
20374
  },
20307
20375
  {
20308
20376
  id: "gpt-5.6-sol",
@@ -20316,7 +20384,10 @@ var SCOUT_RUNTIME_CATALOG_DATA = {
20316
20384
  "high",
20317
20385
  "xhigh",
20318
20386
  "ultra"
20319
- ]
20387
+ ],
20388
+ presentation: {
20389
+ detail: "Frontier"
20390
+ }
20320
20391
  },
20321
20392
  {
20322
20393
  id: "gpt-5.6-terra",
@@ -20330,14 +20401,20 @@ var SCOUT_RUNTIME_CATALOG_DATA = {
20330
20401
  "high",
20331
20402
  "xhigh",
20332
20403
  "ultra"
20333
- ]
20404
+ ],
20405
+ presentation: {
20406
+ detail: "Frontier"
20407
+ }
20334
20408
  },
20335
20409
  {
20336
20410
  id: "gpt-5.6-luna",
20337
20411
  label: "5.6 Luna",
20338
20412
  enabled: true,
20339
20413
  family: "GPT",
20340
- version: "5.6 Luna"
20414
+ version: "5.6 Luna",
20415
+ presentation: {
20416
+ detail: "Efficient"
20417
+ }
20341
20418
  },
20342
20419
  {
20343
20420
  id: "gpt-5.5",
@@ -20351,7 +20428,10 @@ var SCOUT_RUNTIME_CATALOG_DATA = {
20351
20428
  label: "5.5 mini",
20352
20429
  enabled: true,
20353
20430
  family: "GPT",
20354
- version: "5.5 mini"
20431
+ version: "5.5 mini",
20432
+ presentation: {
20433
+ detail: "Fast"
20434
+ }
20355
20435
  }
20356
20436
  ]
20357
20437
  },
@@ -20367,6 +20447,10 @@ var SCOUT_RUNTIME_CATALOG_DATA = {
20367
20447
  "xhigh"
20368
20448
  ],
20369
20449
  defaultReasoningEffort: "high",
20450
+ presentation: {
20451
+ short: "Grok",
20452
+ monogram: "✕"
20453
+ },
20370
20454
  models: [
20371
20455
  {
20372
20456
  id: "grok-4.6",
@@ -20375,7 +20459,10 @@ var SCOUT_RUNTIME_CATALOG_DATA = {
20375
20459
  default: true,
20376
20460
  family: "Grok",
20377
20461
  version: "4.6",
20378
- contextWindowTokens: 500000
20462
+ contextWindowTokens: 500000,
20463
+ presentation: {
20464
+ detail: "Latest"
20465
+ }
20379
20466
  },
20380
20467
  {
20381
20468
  id: "grok-4.5",
@@ -20398,6 +20485,10 @@ var SCOUT_RUNTIME_CATALOG_DATA = {
20398
20485
  "xhigh"
20399
20486
  ],
20400
20487
  defaultReasoningEffort: "high",
20488
+ presentation: {
20489
+ short: "Grok",
20490
+ monogram: "✕"
20491
+ },
20401
20492
  models: [
20402
20493
  {
20403
20494
  id: "grok-4.6",
@@ -20406,7 +20497,10 @@ var SCOUT_RUNTIME_CATALOG_DATA = {
20406
20497
  default: true,
20407
20498
  family: "Grok",
20408
20499
  version: "4.6",
20409
- contextWindowTokens: 500000
20500
+ contextWindowTokens: 500000,
20501
+ presentation: {
20502
+ detail: "Latest"
20503
+ }
20410
20504
  },
20411
20505
  {
20412
20506
  id: "grok-4.5",
@@ -20423,12 +20517,17 @@ var SCOUT_RUNTIME_CATALOG_DATA = {
20423
20517
  label: "Kimi Code",
20424
20518
  enabled: true,
20425
20519
  reasoningEfforts: null,
20520
+ presentation: {
20521
+ short: "Kimi",
20522
+ monogram: "◐"
20523
+ },
20426
20524
  models: []
20427
20525
  },
20428
20526
  {
20429
20527
  id: "flue",
20430
20528
  label: "Flue",
20431
20529
  enabled: true,
20530
+ listed: false,
20432
20531
  reasoningEfforts: null,
20433
20532
  models: []
20434
20533
  },
@@ -20593,6 +20692,10 @@ var SCOUT_RUNTIME_CATALOG = SCOUT_RUNTIME_CATALOG_DATA;
20593
20692
  function scoutRuntimeHarness(harness, catalog = SCOUT_RUNTIME_CATALOG) {
20594
20693
  return catalog.harnesses.find((entry) => entry.id === harness);
20595
20694
  }
20695
+ function isModelSelectableHarness(harness, catalog = SCOUT_RUNTIME_CATALOG) {
20696
+ const entry = scoutRuntimeHarness(harness, catalog);
20697
+ return entry?.enabled === true && entry.models.some((model) => model.enabled);
20698
+ }
20596
20699
  function scoutRuntimeDefaultHarness(catalog = SCOUT_RUNTIME_CATALOG) {
20597
20700
  return catalog.harnesses.find((entry) => entry.enabled && entry.default)?.id ?? catalog.harnesses.find((entry) => entry.enabled)?.id ?? null;
20598
20701
  }
@@ -20649,7 +20752,9 @@ function scoutRuntimeModelCatalog(catalog = SCOUT_RUNTIME_CATALOG) {
20649
20752
  harnesses: [harness.id],
20650
20753
  source: "default",
20651
20754
  ...model.family ? { family: model.family } : {},
20652
- ...model.version ? { version: model.version } : {}
20755
+ ...model.version ? { version: model.version } : {},
20756
+ ...model.default === true ? { isDefault: true } : {},
20757
+ ...model.presentation ? { presentation: model.presentation } : {}
20653
20758
  });
20654
20759
  }
20655
20760
  }
@@ -20695,6 +20800,168 @@ function scoutRuntimeEffortCatalog(catalog = SCOUT_RUNTIME_CATALOG) {
20695
20800
  });
20696
20801
  }
20697
20802
  var SCOUT_RUNTIME_EFFORT_CATALOG = scoutRuntimeEffortCatalog();
20803
+ function parseScoutRuntimeSpec(input) {
20804
+ const raw = input.trim();
20805
+ const parts = raw.split("/");
20806
+ if (!raw || parts.length > 3 || parts.some((part) => !part.trim())) {
20807
+ return {
20808
+ ok: false,
20809
+ error: "runtime must be <harness>[/<model>[/<effort>]]"
20810
+ };
20811
+ }
20812
+ const rawHarness = parts[0].trim().toLowerCase();
20813
+ const harness = rawHarness === "oc" ? "opencode" : rawHarness;
20814
+ if (!isScoutLaunchableHarness(harness)) {
20815
+ return {
20816
+ ok: false,
20817
+ error: `unsupported runtime harness "${parts[0]}"; expected one of: ${SCOUT_LAUNCHABLE_HARNESSES.join(", ")}`
20818
+ };
20819
+ }
20820
+ const model = parts[1]?.trim();
20821
+ const effortRaw = parts[2]?.trim();
20822
+ const reasoningEffort = effortRaw ? normalizeScoutReasoningEffort(effortRaw) : null;
20823
+ if (effortRaw && !reasoningEffort) {
20824
+ return {
20825
+ ok: false,
20826
+ error: `unsupported reasoning effort "${effortRaw}"; expected one of: ${SCOUT_REASONING_EFFORTS.join(", ")}`
20827
+ };
20828
+ }
20829
+ const issues = validateScoutRuntimeTuple({ harness, model, reasoningEffort });
20830
+ if (issues.length > 0) {
20831
+ return { ok: false, error: issues.map((issue) => issue.message).join("; ") };
20832
+ }
20833
+ return {
20834
+ ok: true,
20835
+ value: {
20836
+ harness,
20837
+ ...model ? { model } : {},
20838
+ ...reasoningEffort ? { reasoningEffort } : {}
20839
+ }
20840
+ };
20841
+ }
20842
+ function isScoutLaunchableHarness(value) {
20843
+ if (!value)
20844
+ return false;
20845
+ const normalized = value.trim().toLowerCase();
20846
+ return normalized === "oc" || SCOUT_LAUNCHABLE_HARNESSES.includes(normalized);
20847
+ }
20848
+ function normalizeScoutReasoningEffort(value) {
20849
+ const normalized = value?.trim().toLowerCase();
20850
+ return normalized && SCOUT_REASONING_EFFORTS.includes(normalized) ? normalized : null;
20851
+ }
20852
+ function validateScoutRuntimeTuple(input, catalog, ownedCatalog = SCOUT_RUNTIME_CATALOG) {
20853
+ const rawHarness = input.harness?.trim().toLowerCase();
20854
+ const harness = rawHarness === "oc" ? "opencode" : rawHarness;
20855
+ const model = input.model?.trim();
20856
+ const effortRaw = input.reasoningEffort?.trim();
20857
+ const issues = [];
20858
+ if (harness && !ownedCatalog.harnesses.some((entry) => entry.id === harness)) {
20859
+ issues.push({
20860
+ code: "unsupported_harness",
20861
+ dimension: "harness",
20862
+ message: `unsupported harness "${input.harness}"; expected one of: ${ownedCatalog.harnesses.map((entry) => entry.id).join(", ")}`
20863
+ });
20864
+ return issues;
20865
+ }
20866
+ const effort = effortRaw ? normalizeScoutReasoningEffort(effortRaw) : null;
20867
+ if (effortRaw && !effort) {
20868
+ issues.push({
20869
+ code: "unsupported_reasoning_effort",
20870
+ dimension: "reasoningEffort",
20871
+ message: `unsupported reasoning effort "${effortRaw}"; expected one of: ${SCOUT_REASONING_EFFORTS.join(", ")}`
20872
+ });
20873
+ } else if (effort && harness) {
20874
+ const catalogEffort = catalog?.efforts.find((candidate) => candidate.id === effort);
20875
+ let supported = catalogEffort ? catalogEffort.harnesses.includes(harness) : (scoutRuntimeReasoningEfforts(harness, model, ownedCatalog) ?? []).includes(effort);
20876
+ if (supported && catalogEffort?.models?.length && model) {
20877
+ const harnessModels = new Set(catalog?.models.filter((candidate) => candidate.harnesses.includes(harness)).map((candidate) => candidate.id.toLowerCase()) ?? []);
20878
+ const scopedModels = catalogEffort.models.filter((candidate) => harnessModels.has(candidate.toLowerCase()));
20879
+ if (harnessModels.has(model.toLowerCase()) && scopedModels.length > 0) {
20880
+ supported = scopedModels.some((candidate) => candidate.toLowerCase() === model.toLowerCase());
20881
+ }
20882
+ }
20883
+ if (!supported) {
20884
+ issues.push({
20885
+ code: "reasoning_effort_harness_mismatch",
20886
+ dimension: "reasoningEffort",
20887
+ message: `reasoning effort "${effort}" is not supported by harness "${harness}"`
20888
+ });
20889
+ }
20890
+ }
20891
+ if (model && harness && !isModelSelectableHarness(harness, ownedCatalog)) {
20892
+ issues.push({
20893
+ code: "unsupported_model_dimension",
20894
+ dimension: "model",
20895
+ message: `model selection is not supported by harness "${harness}"`
20896
+ });
20897
+ } else if (model && harness && catalog) {
20898
+ const known = catalog.models.find((candidate) => candidate.id.toLowerCase() === model.toLowerCase());
20899
+ if (known && !known.harnesses.includes(harness)) {
20900
+ issues.push({
20901
+ code: "model_harness_mismatch",
20902
+ dimension: "model",
20903
+ message: `model "${model}" is not supported by harness "${harness}"`
20904
+ });
20905
+ }
20906
+ }
20907
+ return issues;
20908
+ }
20909
+
20910
+ // ../protocol/dist/permission-policy.js
20911
+ var SCOUT_PERMISSION_PROFILES = [
20912
+ "observe",
20913
+ "review",
20914
+ "workspace_write",
20915
+ "sandboxed_write",
20916
+ "trusted_local",
20917
+ "external_sandbox"
20918
+ ];
20919
+ function normalizeScoutPermissionProfile(value) {
20920
+ const normalized = value?.trim().replaceAll("-", "_");
20921
+ return SCOUT_PERMISSION_PROFILES.find((profile) => profile === normalized);
20922
+ }
20923
+
20924
+ // ../protocol/dist/presence.js
20925
+ var PRESENCE_STALE_AFTER_MS = 45000;
20926
+ var PRESENCE_GONE_AFTER_STALE_MS = 60000;
20927
+ function presenceLifecycle(beat, now, options = {}) {
20928
+ if (now < beat.staleAt)
20929
+ return "fresh";
20930
+ const goneAfterStaleMs = options.goneAfterStaleMs ?? PRESENCE_GONE_AFTER_STALE_MS;
20931
+ if (now < beat.staleAt + goneAfterStaleMs)
20932
+ return "stale";
20933
+ return "gone";
20934
+ }
20935
+ function isPresenceGone(beat, now, options = {}) {
20936
+ return presenceLifecycle(beat, now, options) === "gone";
20937
+ }
20938
+
20939
+ // ../protocol/dist/session-handle.js
20940
+ var SCOUT_SESSION_ADDRESS_PREFIX = "session:";
20941
+ var SCOUT_CANONICAL_SESSION_HANDLE_PATTERN = /^sess\.[A-Za-z0-9_-]{10,64}$/;
20942
+ function isScoutSessionHandle(value) {
20943
+ return typeof value === "string" && SCOUT_CANONICAL_SESSION_HANDLE_PATTERN.test(value);
20944
+ }
20945
+ function normalizeScoutSessionHost(value) {
20946
+ if (typeof value !== "string")
20947
+ return "";
20948
+ return value.trim().toLowerCase().replace(/\.+$/, "").replace(/\.local$/, "").replace(/[^a-z0-9.-]+/g, "-").replace(/-+/g, "-").replace(/^[-.]+|[-.]+$/g, "");
20949
+ }
20950
+ var SCOUT_SESSION_HOST_PATTERN = /^[a-z0-9](?:[a-z0-9.-]{0,251}[a-z0-9])?$/;
20951
+ function parseScoutSessionHostAddress(value) {
20952
+ if (typeof value !== "string")
20953
+ return null;
20954
+ const trimmed = value.trim();
20955
+ const bare = trimmed.startsWith(SCOUT_SESSION_ADDRESS_PREFIX) ? trimmed.slice(SCOUT_SESSION_ADDRESS_PREFIX.length) : trimmed;
20956
+ const at = bare.indexOf("@");
20957
+ if (at <= 0 || at !== bare.lastIndexOf("@"))
20958
+ return null;
20959
+ const handle = bare.slice(0, at);
20960
+ const host = normalizeScoutSessionHost(bare.slice(at + 1));
20961
+ if (!isScoutSessionHandle(handle) || !SCOUT_SESSION_HOST_PATTERN.test(host))
20962
+ return null;
20963
+ return { handle, host };
20964
+ }
20698
20965
 
20699
20966
  // ../protocol/dist/runtime-profiles.js
20700
20967
  var SCOUT_RESERVED_RUNTIME_PROFILE_IDS = [
@@ -20716,6 +20983,28 @@ function record(value) {
20716
20983
  function text(value) {
20717
20984
  return typeof value === "string" && value.trim() === value && value.length > 0 ? value : null;
20718
20985
  }
20986
+ function presentation(value, path, errors, keys) {
20987
+ if (value === undefined)
20988
+ return;
20989
+ const input = record(value);
20990
+ if (!input) {
20991
+ errors.push(`${path} must be an object`);
20992
+ return;
20993
+ }
20994
+ const result = {};
20995
+ for (const key of keys) {
20996
+ const field = input[key];
20997
+ if (field === undefined)
20998
+ continue;
20999
+ const parsed = text(field);
21000
+ if (!parsed) {
21001
+ errors.push(`${path}.${key} must be a non-empty trimmed string`);
21002
+ continue;
21003
+ }
21004
+ result[key] = parsed;
21005
+ }
21006
+ return result;
21007
+ }
20719
21008
  function effortList(value, path, errors) {
20720
21009
  if (value === null)
20721
21010
  return null;
@@ -20775,7 +21064,8 @@ function model(value, path, errors) {
20775
21064
  ...text(input.version) ? { version: text(input.version) } : {},
20776
21065
  ...Number.isInteger(contextWindowTokens) && Number(contextWindowTokens) > 0 ? { contextWindowTokens: Number(contextWindowTokens) } : {},
20777
21066
  ...input.reasoningEfforts !== undefined ? { reasoningEfforts: efforts ?? null } : {},
20778
- ...defaultEffort && reasoningEfforts.has(defaultEffort) ? { defaultReasoningEffort: defaultEffort } : {}
21067
+ ...defaultEffort && reasoningEfforts.has(defaultEffort) ? { defaultReasoningEffort: defaultEffort } : {},
21068
+ ...input.presentation !== undefined ? { presentation: presentation(input.presentation, `${path}.presentation`, errors, ["detail"]) } : {}
20779
21069
  };
20780
21070
  }
20781
21071
  function harness(value, path, errors) {
@@ -20837,6 +21127,7 @@ function harness(value, path, errors) {
20837
21127
  ...input.default === true ? { default: true } : {},
20838
21128
  reasoningEfforts: efforts,
20839
21129
  ...defaultEffort && reasoningEfforts.has(defaultEffort) ? { defaultReasoningEffort: defaultEffort } : {},
21130
+ ...input.presentation !== undefined ? { presentation: presentation(input.presentation, `${path}.presentation`, errors, ["short", "monogram"]) } : {},
20840
21131
  models
20841
21132
  };
20842
21133
  }
@@ -20966,11 +21257,27 @@ function parseRouteAliasTarget(rawValue) {
20966
21257
  return null;
20967
21258
  return { kind: "route_alias", alias, value: `alias:${alias}` };
20968
21259
  }
21260
+ function parseSessionHostAddressTarget(value) {
21261
+ const address = parseScoutSessionHostAddress(value);
21262
+ if (!address) {
21263
+ return null;
21264
+ }
21265
+ return {
21266
+ kind: "session_id",
21267
+ sessionId: address.handle,
21268
+ host: address.host,
21269
+ value: `session:${address.handle}@${address.host}`
21270
+ };
21271
+ }
20969
21272
  function parseSessionRouteTarget(rawValue) {
20970
21273
  const value = rawValue.replace(/^@+/, "");
20971
21274
  if (!isRouteValue(value)) {
20972
21275
  return null;
20973
21276
  }
21277
+ const hostAddress = parseSessionHostAddressTarget(value);
21278
+ if (hostAddress) {
21279
+ return hostAddress;
21280
+ }
20974
21281
  const harnessSeparator = value.indexOf(":");
20975
21282
  if (harnessSeparator > 0) {
20976
21283
  const maybeHarness = value.slice(0, harnessSeparator);
@@ -21037,6 +21344,10 @@ function parseScoutComposerRouteTarget(value) {
21037
21344
  return prefixed;
21038
21345
  }
21039
21346
  }
21347
+ const hostAddress = parseSessionHostAddressTarget(token);
21348
+ if (hostAddress) {
21349
+ return hostAddress;
21350
+ }
21040
21351
  return parseAgentLabelTarget(token);
21041
21352
  }
21042
21353
 
@@ -21109,7 +21420,7 @@ function validateScoutRendezvousCodename(codename) {
21109
21420
 
21110
21421
  // ../runtime/dist/claude-statusline.js
21111
21422
  import { appendFile, mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
21112
- import { basename as basename3, dirname as dirname6, join as join9 } from "node:path";
21423
+ import { basename as basename3, dirname as dirname7, join as join9 } from "node:path";
21113
21424
 
21114
21425
  // ../runtime/dist/claude-session-records.js
21115
21426
  var TRANSCRIPT_TAIL_BYTES = 256 * 1024;
@@ -21129,7 +21440,7 @@ async function writeClaudeStatuslineDelegate(delegate, path = resolveClaudeStatu
21129
21440
  version: 1,
21130
21441
  ...delegate
21131
21442
  };
21132
- await mkdir2(dirname6(path), { recursive: true });
21443
+ await mkdir2(dirname7(path), { recursive: true });
21133
21444
  await writeFile2(path, JSON.stringify(next, null, 2) + `
21134
21445
  `, "utf8");
21135
21446
  return next;
@@ -21146,7 +21457,7 @@ function isOpenScoutClaudeStatuslineCommand(command, wrapperPath = resolveClaude
21146
21457
  // ../runtime/dist/managed-installs.js
21147
21458
  import { createHash as createHash3 } from "node:crypto";
21148
21459
  import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile3 } from "node:fs/promises";
21149
- import { dirname as dirname7 } from "node:path";
21460
+ import { dirname as dirname8 } from "node:path";
21150
21461
  function emptyManagedInstallsFile(now = Date.now()) {
21151
21462
  return {
21152
21463
  version: 1,
@@ -21186,7 +21497,7 @@ async function readManagedInstallsFile(path = resolveOpenScoutSupportPaths().man
21186
21497
  }
21187
21498
  async function writeManagedInstallsFile(file, path = resolveOpenScoutSupportPaths().managedInstallsPath) {
21188
21499
  assertTestIsolatedUserData("write the managed-installs registry", "OPENSCOUT_SUPPORT_DIRECTORY");
21189
- await mkdir3(dirname7(path), { recursive: true });
21500
+ await mkdir3(dirname8(path), { recursive: true });
21190
21501
  await writeFile3(path, JSON.stringify(file, null, 2) + `
21191
21502
  `, "utf8");
21192
21503
  }
@@ -21215,7 +21526,7 @@ async function upsertManagedInstall(input, now = Date.now()) {
21215
21526
  // ../runtime/dist/user-project-hints.js
21216
21527
  import { readdir, readFile as readFile5, stat } from "node:fs/promises";
21217
21528
  import { homedir as homedir7 } from "node:os";
21218
- import { dirname as dirname8, join as join10, resolve as resolve3 } from "node:path";
21529
+ import { dirname as dirname9, join as join10, resolve as resolve3 } from "node:path";
21219
21530
  import { fileURLToPath as fileURLToPath2 } from "node:url";
21220
21531
  var PROJECT_HINT_MARKERS = [
21221
21532
  ".git",
@@ -21252,7 +21563,7 @@ async function resolveExistingDirectoryHint(pathLike) {
21252
21563
  return absolutePath;
21253
21564
  }
21254
21565
  if (info.isFile()) {
21255
- return dirname8(absolutePath);
21566
+ return dirname9(absolutePath);
21256
21567
  }
21257
21568
  } catch {
21258
21569
  return null;
@@ -21279,7 +21590,7 @@ async function findLikelyProjectRoot(absolutePath) {
21279
21590
  }
21280
21591
  }
21281
21592
  }
21282
- const parent = dirname8(current);
21593
+ const parent = dirname9(current);
21283
21594
  if (parent === current) {
21284
21595
  return lastCandidate ?? absolutePath;
21285
21596
  }
@@ -21420,7 +21731,7 @@ async function appendCursorWorkspacePaths(home, roots) {
21420
21731
  }
21421
21732
  const wsRaw = await readFile5(wsFile, "utf8");
21422
21733
  const wsDoc = JSON.parse(wsRaw);
21423
- const wsDir = dirname8(wsFile);
21734
+ const wsDir = dirname9(wsFile);
21424
21735
  for (const f of wsDoc.folders ?? []) {
21425
21736
  if (typeof f.path !== "string" || !f.path) {
21426
21737
  continue;
@@ -22214,7 +22525,7 @@ async function readJsonFile(filePath) {
22214
22525
  }
22215
22526
  }
22216
22527
  async function writeJsonFile(filePath, value) {
22217
- await mkdir4(dirname9(filePath), { recursive: true });
22528
+ await mkdir4(dirname10(filePath), { recursive: true });
22218
22529
  await writeFile4(filePath, JSON.stringify(value, null, 2) + `
22219
22530
  `, "utf8");
22220
22531
  }
@@ -22684,7 +22995,7 @@ async function seedWorkspaceRoots(options) {
22684
22995
  const roots = new Set;
22685
22996
  const currentProjectRoot = options.currentDirectory ? await findNearestProjectRoot(options.currentDirectory) : null;
22686
22997
  if (currentProjectRoot) {
22687
- roots.add(dirname9(currentProjectRoot));
22998
+ roots.add(dirname10(currentProjectRoot));
22688
22999
  }
22689
23000
  const legacyRoot = options.legacyRelayConfig?.projectRoot?.trim();
22690
23001
  if (legacyRoot) {
@@ -22692,7 +23003,7 @@ async function seedWorkspaceRoots(options) {
22692
23003
  }
22693
23004
  for (const record2 of Object.values(options.legacyAgents ?? {})) {
22694
23005
  if (record2.cwd?.trim()) {
22695
- roots.add(dirname9(normalizePath(record2.cwd)));
23006
+ roots.add(dirname10(normalizePath(record2.cwd)));
22696
23007
  }
22697
23008
  }
22698
23009
  if (roots.size === 0) {
@@ -22780,7 +23091,7 @@ async function writeOpenScoutSettings(settings, options = {}) {
22780
23091
  return normalized;
22781
23092
  }
22782
23093
  var SCOUT_SKILL_FILE_NAME = "SKILL.md";
22783
- var SETUP_MODULE_DIRECTORY = dirname9(fileURLToPath3(import.meta.url));
23094
+ var SETUP_MODULE_DIRECTORY = dirname10(fileURLToPath3(import.meta.url));
22784
23095
  var SCOUT_SKILL_REPO_ROOT = resolve4(SETUP_MODULE_DIRECTORY, "..", "..", "..");
22785
23096
  function scoutSkillInstallTargets(home = homedir8()) {
22786
23097
  return [
@@ -22831,7 +23142,7 @@ async function installScoutSkillToHarnesses() {
22831
23142
  for (const installTarget of scoutSkillInstallTargets()) {
22832
23143
  const { id, harness: harness2, target } = installTarget;
22833
23144
  try {
22834
- await mkdir4(dirname9(target), { recursive: true });
23145
+ await mkdir4(dirname10(target), { recursive: true });
22835
23146
  await writeFile4(target, content, "utf8");
22836
23147
  await upsertManagedInstall({
22837
23148
  kind: "skill",
@@ -22895,7 +23206,7 @@ async function installClaudeStatuslineTool() {
22895
23206
  const command = shellQuote(wrapperPath);
22896
23207
  try {
22897
23208
  const scoutInvocation = resolveScoutStatuslineInvocation();
22898
- await mkdir4(dirname9(wrapperPath), { recursive: true });
23209
+ await mkdir4(dirname10(wrapperPath), { recursive: true });
22899
23210
  await writeFile4(wrapperPath, [
22900
23211
  "#!/bin/sh",
22901
23212
  "set -eu",
@@ -23086,7 +23397,7 @@ async function findNearestProjectRoot(startDirectory) {
23086
23397
  if (await pathExists2(projectConfigPath(current)) || await pathExists2(join11(current, "package.json")) || await pathExists2(join11(current, "AGENTS.md")) || await pathExists2(join11(current, "CLAUDE.md"))) {
23087
23398
  lastCandidate = current;
23088
23399
  }
23089
- const parent = dirname9(current);
23400
+ const parent = dirname10(current);
23090
23401
  if (parent === current) {
23091
23402
  return lastCandidate;
23092
23403
  }
@@ -23483,7 +23794,7 @@ async function resolveInferredAgent(projectRoot, settings, override) {
23483
23794
  return mergeResolvedAgentConfig(base, override, settings);
23484
23795
  }
23485
23796
  async function buildProjectInventoryEntry(agent, sourceRoot) {
23486
- const manifestRoot = agent.projectConfigPath ? normalizePath(join11(dirname9(agent.projectConfigPath), "..")) : null;
23797
+ const manifestRoot = agent.projectConfigPath ? normalizePath(join11(dirname10(agent.projectConfigPath), "..")) : null;
23487
23798
  const manifest = manifestRoot ? await readProjectConfig(manifestRoot) : null;
23488
23799
  const markers = await detectHarnessMarkers(agent.projectRoot);
23489
23800
  const harnesses = new Map;
@@ -23734,7 +24045,7 @@ async function initializeOpenScoutSetup(options = {}) {
23734
24045
  // ../runtime/dist/user-config.js
23735
24046
  import { existsSync as existsSync10, readFileSync as readFileSync7, statSync as statSync2, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "node:fs";
23736
24047
  import { homedir as homedir9 } from "node:os";
23737
- import { dirname as dirname10, join as join12 } from "node:path";
24048
+ import { dirname as dirname11, join as join12 } from "node:path";
23738
24049
  function userConfigPath() {
23739
24050
  return join12(process.env.OPENSCOUT_HOME ?? join12(homedir9(), ".openscout"), "user.json");
23740
24051
  }
@@ -23777,7 +24088,7 @@ function loadUserConfig(now = Date.now()) {
23777
24088
  function saveUserConfig(config) {
23778
24089
  assertTestIsolatedUserData("write the OpenScout user config", "OPENSCOUT_HOME");
23779
24090
  const configPath = userConfigPath();
23780
- mkdirSync5(dirname10(configPath), { recursive: true });
24091
+ mkdirSync5(dirname11(configPath), { recursive: true });
23781
24092
  writeFileSync5(configPath, JSON.stringify(config, null, 2) + `
23782
24093
  `, "utf8");
23783
24094
  userConfigCache = null;
@@ -23854,7 +24165,7 @@ async function nearestProjectConfig(startDirectory) {
23854
24165
  projectConfigPath: candidate
23855
24166
  };
23856
24167
  }
23857
- const parent = dirname11(current);
24168
+ const parent = dirname12(current);
23858
24169
  if (parent === current)
23859
24170
  break;
23860
24171
  current = parent;
@@ -27487,6 +27798,53 @@ CREATE INDEX IF NOT EXISTS idx_mission_log_entries_mission_at
27487
27798
  CREATE INDEX IF NOT EXISTS idx_mission_log_entries_actor_at
27488
27799
  ON mission_log_entries (actor_id, at DESC);
27489
27800
  `;
27801
+ // ../runtime/dist/local-agent-transports.js
27802
+ var directLocalAgentTransports = new Set([
27803
+ "codex_app_server",
27804
+ "claude_stream_json",
27805
+ "pi_rpc",
27806
+ "grok_acp",
27807
+ "kimi_acp",
27808
+ "cursor_acp",
27809
+ "opencode_acp",
27810
+ "devin_acp"
27811
+ ]);
27812
+
27813
+ // ../runtime/dist/broker-endpoint-selection.js
27814
+ var TERMINAL_ENDPOINT_STATES = new Set([
27815
+ "failed",
27816
+ "superseded",
27817
+ "stopped"
27818
+ ]);
27819
+ // ../runtime/dist/broker-local-invocation-helpers.js
27820
+ var STALE_WORKING_FLIGHT_NO_ENDPOINT_GRACE_MS = 2 * 60000;
27821
+
27822
+ // ../runtime/dist/broker-dispatch-job.js
27823
+ var TERMINAL_DISPATCH_JOB_STATES = new Set([
27824
+ "completed",
27825
+ "failed",
27826
+ "cancelled"
27827
+ ]);
27828
+
27829
+ // ../runtime/dist/history-rotation.js
27830
+ var TERMINAL_DELIVERY_STATUSES = new Set([
27831
+ "completed",
27832
+ "failed",
27833
+ "cancelled",
27834
+ "acknowledged"
27835
+ ]);
27836
+ function applyHistoryRotationEviction(snapshot, evicted) {
27837
+ for (const id of evicted.messageIds) {
27838
+ delete snapshot.messages[id];
27839
+ }
27840
+ for (const id of evicted.invocationIds) {
27841
+ delete snapshot.invocations[id];
27842
+ }
27843
+ for (const id of evicted.flightIds) {
27844
+ delete snapshot.flights[id];
27845
+ }
27846
+ }
27847
+
27490
27848
  // ../runtime/dist/broker.js
27491
27849
  function createRuntimeId(prefix) {
27492
27850
  return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
@@ -27580,11 +27938,18 @@ class InMemoryControlRuntime {
27580
27938
  endpointIdsByAgentId = new Map;
27581
27939
  bindingIdsByConversationId = new Map;
27582
27940
  flightIdByInvocationId = new Map;
27941
+ retiredActorIds = new Set;
27583
27942
  constructor(initial = {}, options = {}) {
27584
27943
  this.registry = createRuntimeRegistrySnapshot(initial);
27585
27944
  this.localNodeId = options.localNodeId;
27945
+ for (const actorId of options.retiredActorIds ?? []) {
27946
+ this.retiredActorIds.add(actorId);
27947
+ }
27586
27948
  this.rebuildIndexes();
27587
27949
  }
27950
+ isRetiredActor(actorId) {
27951
+ return this.retiredActorIds.has(actorId);
27952
+ }
27588
27953
  snapshot() {
27589
27954
  return createRuntimeRegistrySnapshot({
27590
27955
  nodes: { ...this.registry.nodes },
@@ -27727,6 +28092,7 @@ class InMemoryControlRuntime {
27727
28092
  return;
27728
28093
  case "stream.subscribe":
27729
28094
  return;
28095
+ case "channel.member.remove":
27730
28096
  case "channel.invite.create":
27731
28097
  case "channel.invite.revoke":
27732
28098
  case "channel.invite.redeem":
@@ -27749,13 +28115,15 @@ class InMemoryControlRuntime {
27749
28115
  });
27750
28116
  }
27751
28117
  async upsertActor(actor) {
28118
+ this.retiredActorIds.delete(actor.id);
27752
28119
  this.registry.actors[actor.id] = {
27753
28120
  id: actor.id,
27754
28121
  kind: actor.kind,
27755
28122
  displayName: actor.displayName,
27756
28123
  handle: actor.handle,
27757
28124
  labels: actor.labels,
27758
- metadata: actor.metadata
28125
+ metadata: actor.metadata,
28126
+ createdAt: actor.createdAt ?? this.registry.actors[actor.id]?.createdAt ?? Date.now()
27759
28127
  };
27760
28128
  this.emit({
27761
28129
  id: createRuntimeId("evt"),
@@ -27767,6 +28135,7 @@ class InMemoryControlRuntime {
27767
28135
  });
27768
28136
  }
27769
28137
  async upsertAgent(agent) {
28138
+ this.retiredActorIds.delete(agent.id);
27770
28139
  if (!this.registry.actors[agent.id]) {
27771
28140
  this.registry.actors[agent.id] = {
27772
28141
  id: agent.id,
@@ -27774,7 +28143,8 @@ class InMemoryControlRuntime {
27774
28143
  displayName: agent.displayName,
27775
28144
  handle: agent.handle,
27776
28145
  labels: agent.labels,
27777
- metadata: agent.metadata
28146
+ metadata: agent.metadata,
28147
+ createdAt: agent.createdAt ?? Date.now()
27778
28148
  };
27779
28149
  }
27780
28150
  this.registry.agents[agent.id] = agent;
@@ -27788,6 +28158,7 @@ class InMemoryControlRuntime {
27788
28158
  });
27789
28159
  }
27790
28160
  upsertAgentIdentity(input) {
28161
+ this.retiredActorIds.delete(input.id);
27791
28162
  if (!this.registry.actors[input.id]) {
27792
28163
  this.registry.actors[input.id] = {
27793
28164
  id: input.id,
@@ -27795,7 +28166,8 @@ class InMemoryControlRuntime {
27795
28166
  displayName: input.displayName,
27796
28167
  handle: input.handle,
27797
28168
  labels: input.labels,
27798
- metadata: input.metadata
28169
+ metadata: input.metadata,
28170
+ createdAt: Date.now()
27799
28171
  };
27800
28172
  }
27801
28173
  const partial = {
@@ -27865,6 +28237,38 @@ class InMemoryControlRuntime {
27865
28237
  payload: { endpointId: id }
27866
28238
  });
27867
28239
  }
28240
+ deleteAgent(id) {
28241
+ const endpointIds = this.endpointIdsByAgentId.get(id);
28242
+ if (endpointIds) {
28243
+ for (const endpointId of [...endpointIds]) {
28244
+ this.deleteEndpoint(endpointId);
28245
+ }
28246
+ }
28247
+ if (!this.registry.agents[id])
28248
+ return;
28249
+ delete this.registry.agents[id];
28250
+ }
28251
+ deleteActor(id) {
28252
+ this.retiredActorIds.add(id);
28253
+ if (!this.registry.actors[id])
28254
+ return;
28255
+ delete this.registry.actors[id];
28256
+ }
28257
+ applyHistoryRotation(evicted) {
28258
+ const flightIds = new Set(evicted.flightIds);
28259
+ applyHistoryRotationEviction(this.registry, {
28260
+ messageIds: new Set(evicted.messageIds),
28261
+ invocationIds: new Set(evicted.invocationIds),
28262
+ flightIds
28263
+ });
28264
+ if (flightIds.size > 0) {
28265
+ for (const [invocationId, flightId] of this.flightIdByInvocationId) {
28266
+ if (flightIds.has(flightId)) {
28267
+ this.flightIdByInvocationId.delete(invocationId);
28268
+ }
28269
+ }
28270
+ }
28271
+ }
27868
28272
  async upsertConversation(conversation) {
27869
28273
  const metadata = conversation.metadata;
27870
28274
  if (typeof metadata?.createdAt !== "number" || typeof metadata?.updatedAt !== "number") {
@@ -27969,6 +28373,18 @@ class InMemoryControlRuntime {
27969
28373
  });
27970
28374
  return deliveries;
27971
28375
  }
28376
+ async correctMessage(message) {
28377
+ if (!asyncMessageRecordView(this.registry.messages))
28378
+ this.registry.messages[message.id] = message;
28379
+ this.emit({
28380
+ id: createRuntimeId("evt"),
28381
+ kind: "message.corrected",
28382
+ ts: Date.now(),
28383
+ actorId: message.actorId,
28384
+ nodeId: message.originNodeId,
28385
+ payload: { message }
28386
+ });
28387
+ }
27972
28388
  async commitMessage(message, deliveries) {
27973
28389
  if (!asyncMessageRecordView(this.registry.messages))
27974
28390
  this.registry.messages[message.id] = message;
@@ -28162,10 +28578,17 @@ class InMemoryControlRuntime {
28162
28578
  }
28163
28579
  }
28164
28580
  }
28581
+ // ../runtime/dist/scout-bridge-command.js
28582
+ var ENTRYPOINT = String.raw`(?:scout\.(?:mjs|ts|js)|\/bin\/scout|\/main\.mjs)`;
28583
+ var SUBCOMMAND = String.raw`\s+(mcp|channel|mesh\s+bridge)(?:\s|$)`;
28584
+ var RUNTIME = String.raw`(?:\S*\/)?(?:bun|node)(?:\s+(?!(?:-e|-p|--eval|--print)(?:[\s=]|$))-[\w-]+(?:=\S+)?)*`;
28585
+ var SCRIPT_PREFIX = String.raw`(?:[^-\s](?:(?!\s-|\.(?:[cm]?js|ts)\s).)*?)?`;
28586
+ var SCOUT_BRIDGE_COMMAND = new RegExp(String.raw`^(?:${RUNTIME}\s+${SCRIPT_PREFIX}|\S*?)${ENTRYPOINT}${SUBCOMMAND}`);
28587
+ var SCOUT_BRIDGE_BINARY = new RegExp(String.raw`^(?:${RUNTIME}\s+(?:${SCRIPT_PREFIX}\/)?|\S*\/)?scout-mcp(?:\s|$)`);
28165
28588
  // ../runtime/dist/conversation-thread-artifact.js
28166
28589
  import { createHash as createHash4, randomBytes as randomBytes2 } from "node:crypto";
28167
28590
  import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync8, readdirSync, renameSync as renameSync4, rmSync as rmSync3, statSync as statSync3, writeFileSync as writeFileSync6 } from "node:fs";
28168
- import { basename as basename5, dirname as dirname12, join as join14 } from "node:path";
28591
+ import { basename as basename5, dirname as dirname13, join as join14 } from "node:path";
28169
28592
  var NATIVE_READ_THREAD_ARTIFACT_SCHEMA = "openscout.native.read.thread-cache/v1";
28170
28593
  var NATIVE_READ_THREAD_ARTIFACT_VERSION = 1;
28171
28594
  var NATIVE_READ_THREAD_MAX_BYTES = 256 * 1024;
@@ -28375,7 +28798,7 @@ function readExistingCursor(path) {
28375
28798
  }
28376
28799
  }
28377
28800
  function writeAtomically(path, contents) {
28378
- const directory = dirname12(path);
28801
+ const directory = dirname13(path);
28379
28802
  const temporaryPath = join14(directory, `.${basename5(path)}.${process.pid}.${randomBytes2(6).toString("hex")}.tmp`);
28380
28803
  mkdirSync6(directory, { recursive: true, mode: 448 });
28381
28804
  try {
@@ -28463,11 +28886,17 @@ class ConversationThreadArtifactPublisher {
28463
28886
  }
28464
28887
  }
28465
28888
 
28889
+ // ../runtime/dist/guest-access.js
28890
+ var GUEST_GRANT_MAX_TTL_MS = 30 * 24 * 60 * 60 * 1000;
28891
+ var GUEST_ASK_MAX_TASK_BYTES = 32 * 1024;
28892
+
28466
28893
  // ../runtime/dist/budget-observations.js
28467
28894
  var QUOTA_HISTORY_BUCKET_MS = 60 * 60 * 1000;
28468
28895
 
28469
28896
  // ../runtime/dist/sqlite-store.js
28470
28897
  var RUNTIME_SESSION_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
28898
+ var QUOTA_HISTORY_RETENTION_MS = 7 * 24 * 60 * 60 * 1000 + 60 * 60 * 1000;
28899
+ var QUOTA_HISTORY_PRUNE_INTERVAL_MS = 10 * 60 * 1000;
28471
28900
  // ../runtime/dist/mesh-peer-auth.js
28472
28901
  import { createHash as createHash5, randomBytes as randomBytes3 } from "node:crypto";
28473
28902
  var PEER_AUTH_HEADERS = {
@@ -33294,7 +33723,7 @@ async function requestJsonWithBun2(connect, socketPath, payload, timeoutMs) {
33294
33723
 
33295
33724
  // ../runtime/dist/system-probes/git-build-info.js
33296
33725
  import { existsSync as existsSync14, realpathSync, statSync as statSync4 } from "node:fs";
33297
- import { dirname as dirname13, resolve as resolve6 } from "node:path";
33726
+ import { dirname as dirname14, resolve as resolve6 } from "node:path";
33298
33727
  var staticMetadataByRepo = new Map;
33299
33728
  function realpathOrResolved(path) {
33300
33729
  try {
@@ -33307,7 +33736,7 @@ function directoryOrParent(path) {
33307
33736
  const resolved = resolve6(path);
33308
33737
  try {
33309
33738
  const stat3 = statSync4(resolved);
33310
- return stat3.isDirectory() ? resolved : dirname13(resolved);
33739
+ return stat3.isDirectory() ? resolved : dirname14(resolved);
33311
33740
  } catch {
33312
33741
  return resolved;
33313
33742
  }
@@ -33318,7 +33747,7 @@ function canonicalRepoRoot(rawPath) {
33318
33747
  if (existsSync14(resolve6(current, ".git"))) {
33319
33748
  return realpathOrResolved(current);
33320
33749
  }
33321
- const parent = dirname13(current);
33750
+ const parent = dirname14(current);
33322
33751
  if (parent === current) {
33323
33752
  return realpathOrResolved(directoryOrParent(rawPath));
33324
33753
  }
@@ -34168,6 +34597,7 @@ async function readTmuxPaneLocal(key, ctx) {
34168
34597
  try {
34169
34598
  if (parsed.kind === "detail") {
34170
34599
  const { stdout: stdout2 } = await execProbeFile(ctx, tmuxBin(), [
34600
+ "-u",
34171
34601
  ...tmuxSocketArgs(parsed.socketPath),
34172
34602
  "display-message",
34173
34603
  "-p",
@@ -34314,7 +34744,7 @@ var herdrTopologyCache = new Map;
34314
34744
  import { createReadStream } from "node:fs";
34315
34745
  import { readdir as readdir3, stat as stat3 } from "node:fs/promises";
34316
34746
  import { homedir as homedir13 } from "node:os";
34317
- import { basename as basename6, dirname as dirname14, join as join16, resolve as resolve7 } from "node:path";
34747
+ import { basename as basename6, dirname as dirname15, join as join16, resolve as resolve7 } from "node:path";
34318
34748
  import { createInterface } from "node:readline";
34319
34749
  function positiveInteger(value, fallback, max) {
34320
34750
  return Number.isFinite(value) && value > 0 ? Math.min(max, Math.floor(value)) : fallback;
@@ -34345,7 +34775,7 @@ function extractProjectName(filePath) {
34345
34775
  const claudeMatch = filePath.match(/\.claude\/projects\/[^/]*-dev-([^/]+)/);
34346
34776
  if (claudeMatch?.[1])
34347
34777
  return claudeMatch[1];
34348
- return basename6(dirname14(filePath)) || "unknown";
34778
+ return basename6(dirname15(filePath)) || "unknown";
34349
34779
  }
34350
34780
  function detectAgent(filePath, fallback = "unknown") {
34351
34781
  if (filePath.includes(".claude"))
@@ -35301,7 +35731,7 @@ function notFoundResponse(presence, participantId) {
35301
35731
  };
35302
35732
  }
35303
35733
  // ../runtime/dist/local-agents.js
35304
- import { dirname as dirname15, join as join19, resolve as resolve10 } from "node:path";
35734
+ import { dirname as dirname16, join as join19, resolve as resolve10 } from "node:path";
35305
35735
  import { fileURLToPath as fileURLToPath4 } from "node:url";
35306
35736
 
35307
35737
  // ../agent-sessions/dist/secret-redaction.js
@@ -36841,7 +37271,8 @@ class RequesterWaitTimeoutError extends Error {
36841
37271
  }
36842
37272
 
36843
37273
  // ../runtime/dist/acp-agent-invocation.js
36844
- var DEFAULT_ACP_HARD_CEILING_MS = 30 * 60000;
37274
+ var DEFAULT_ACP_HARD_CEILING_MS = 60 * 60000;
37275
+ var DEFAULT_ACP_HARD_CEILING_MAX_MS = 6 * 60 * 60000;
36845
37276
  var activeAcpSessions = new Map;
36846
37277
 
36847
37278
  // ../runtime/dist/claude-stream-json.js
@@ -37742,7 +38173,7 @@ var LOCAL_AGENT_SYSTEM_PROMPT_TEMPLATE_HINT = [
37742
38173
  var DEFAULT_RELAY_AGENT_ORPHAN_GRACE_MS = 15 * 60000;
37743
38174
 
37744
38175
  // ../runtime/dist/local-agents.js
37745
- var MODULE_DIRECTORY = dirname15(fileURLToPath4(import.meta.url));
38176
+ var MODULE_DIRECTORY = dirname16(fileURLToPath4(import.meta.url));
37746
38177
  var OPENSCOUT_REPO_ROOT = resolve10(MODULE_DIRECTORY, "..", "..", "..");
37747
38178
  var DEFAULT_ONE_TIME_LOCAL_AGENT_CARD_TTL_MS = 24 * 60 * 60 * 1000;
37748
38179
  function parsePositiveInteger2(value, fallback) {
@@ -37759,6 +38190,8 @@ var TMUX_VERIFY_IDLE_DEADLINE_MS = parseNonNegativeInteger(process.env.OPENSCOUT
37759
38190
  var TMUX_VERIFY_BUSY_DEADLINE_MS = parseNonNegativeInteger(process.env.OPENSCOUT_TMUX_VERIFY_BUSY_DEADLINE_MS, 15000);
37760
38191
  var TMUX_DEFAULT_COLUMNS = parsePositiveInteger2(process.env.OPENSCOUT_LOCAL_AGENT_TMUX_COLUMNS, 160);
37761
38192
  var TMUX_DEFAULT_ROWS = parsePositiveInteger2(process.env.OPENSCOUT_LOCAL_AGENT_TMUX_ROWS, 48);
38193
+ var TMUX_READY_TIMEOUT_MS = parseNonNegativeInteger(process.env.OPENSCOUT_TMUX_READY_TIMEOUT_MS, 45000);
38194
+ var TMUX_READY_CEILING_MS = parseNonNegativeInteger(process.env.OPENSCOUT_TMUX_READY_CEILING_MS, 120000);
37762
38195
  // ../runtime/dist/provisional-agent-names-config.js
37763
38196
  import { existsSync as existsSync18, readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "node:fs";
37764
38197
  import { homedir as homedir15 } from "node:os";
@@ -37868,25 +38301,6 @@ function describeProvisionalAgentNamePool(config = loadUserConfig()) {
37868
38301
  }
37869
38302
  // ../runtime/dist/control-plane-agents.js
37870
38303
  var DEFAULT_ONE_TIME_SCOUT_AGENT_CARD_TTL_MS = 24 * 60 * 60 * 1000;
37871
- // ../runtime/dist/local-agent-transports.js
37872
- var directLocalAgentTransports = new Set([
37873
- "codex_app_server",
37874
- "claude_stream_json",
37875
- "pi_rpc",
37876
- "grok_acp",
37877
- "kimi_acp",
37878
- "cursor_acp",
37879
- "opencode_acp",
37880
- "devin_acp"
37881
- ]);
37882
-
37883
- // ../runtime/dist/broker-endpoint-selection.js
37884
- var TERMINAL_ENDPOINT_STATES = new Set([
37885
- "failed",
37886
- "superseded",
37887
- "stopped"
37888
- ]);
37889
-
37890
38304
  // ../runtime/dist/scout-broker.js
37891
38305
  function resolveScoutBrokerUrl() {
37892
38306
  const explicit = process.env.OPENSCOUT_BROKER_URL?.trim();
@@ -37972,6 +38386,74 @@ function formatStoredStringList(value) {
37972
38386
  function setConfigValue(config, key, value) {
37973
38387
  config[key] = value;
37974
38388
  }
38389
+ function normalizeRuntimeShortlistInput(value) {
38390
+ if (!Array.isArray(value)) {
38391
+ throw new Error("runtime-shortlist expects a list of <harness>[/<model>] specs");
38392
+ }
38393
+ const specs = value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter((entry) => entry.length > 0);
38394
+ for (const spec of specs) {
38395
+ const parsed = parseScoutRuntimeSpec(spec);
38396
+ if (!parsed.ok) {
38397
+ throw new Error(`invalid runtime spec "${spec}": ${parsed.error}`);
38398
+ }
38399
+ if (parsed.value.reasoningEffort) {
38400
+ throw new Error(`invalid runtime spec "${spec}": shortlist entries pin a model, not an effort — use runtime-presets for effort`);
38401
+ }
38402
+ }
38403
+ return specs;
38404
+ }
38405
+ function normalizeRuntimePresetId(raw) {
38406
+ const id = normalizeAgentSelectorSegment(typeof raw === "string" ? raw : "");
38407
+ if (!id) {
38408
+ throw new Error("runtime preset needs an id — use id[:Label]=<harness>[/<model>[/<effort>]]");
38409
+ }
38410
+ if (SCOUT_RESERVED_RUNTIME_PROFILE_IDS.includes(id)) {
38411
+ throw new Error(`runtime preset id "${id}" is a reserved runtime profile name`);
38412
+ }
38413
+ if (isScoutLaunchableHarness(id)) {
38414
+ throw new Error(`runtime preset id "${id}" collides with a launchable harness`);
38415
+ }
38416
+ if (SCOUT_REASONING_EFFORTS.includes(id)) {
38417
+ throw new Error(`runtime preset id "${id}" collides with a reasoning effort`);
38418
+ }
38419
+ return id;
38420
+ }
38421
+ function normalizeRuntimePresetInput(value) {
38422
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
38423
+ throw new Error("runtime preset must be { id, label?, runtime }");
38424
+ }
38425
+ const record2 = value;
38426
+ const id = normalizeRuntimePresetId(record2.id);
38427
+ const runtime = typeof record2.runtime === "string" ? record2.runtime.trim() : "";
38428
+ const parsed = parseScoutRuntimeSpec(runtime);
38429
+ if (!parsed.ok) {
38430
+ throw new Error(`invalid runtime spec for preset "${id}": ${parsed.error}`);
38431
+ }
38432
+ const label = typeof record2.label === "string" && record2.label.trim() ? record2.label.trim() : undefined;
38433
+ return { id, ...label ? { label } : {}, runtime };
38434
+ }
38435
+ function parseRuntimePresetItem(item) {
38436
+ const trimmed = item.trim();
38437
+ const eq = trimmed.indexOf("=");
38438
+ if (eq < 0) {
38439
+ throw new Error(`preset "${trimmed}" must be id[:Label]=<harness>[/<model>[/<effort>]]`);
38440
+ }
38441
+ const head = trimmed.slice(0, eq).trim();
38442
+ const runtime = trimmed.slice(eq + 1).trim();
38443
+ const colon = head.indexOf(":");
38444
+ const id = colon < 0 ? head : head.slice(0, colon).trim();
38445
+ const label = colon < 0 ? undefined : head.slice(colon + 1).trim() || undefined;
38446
+ return normalizeRuntimePresetInput({ id, ...label ? { label } : {}, runtime });
38447
+ }
38448
+ function normalizeRuntimePresetsInput(value) {
38449
+ if (!Array.isArray(value)) {
38450
+ throw new Error("runtime-presets expects a list of id[:Label]=<spec> items");
38451
+ }
38452
+ return value.map((entry) => typeof entry === "string" ? parseRuntimePresetItem(entry) : normalizeRuntimePresetInput(entry));
38453
+ }
38454
+ function formatRuntimePresetSetting(preset) {
38455
+ return `${preset.id}${preset.label ? `:${preset.label}` : ""}=${preset.runtime}`;
38456
+ }
37975
38457
  function clearConfigValue(config, key) {
37976
38458
  delete config[key];
37977
38459
  }
@@ -38176,6 +38658,46 @@ var USER_CONFIG_FIELDS = [
38176
38658
  parse: parseStringValue,
38177
38659
  resolveGet: (config) => formatStoredString(config.provisionalAgentNamesFile),
38178
38660
  formatSummary: (config) => formatStoredString(config.provisionalAgentNamesFile) || "—"
38661
+ },
38662
+ {
38663
+ id: "runtime-shortlist",
38664
+ key: "runtimeShortlist",
38665
+ label: "Runtime model shortlist",
38666
+ kind: "string-list",
38667
+ summary: "Models pinned first in runtime pickers (<harness>[/<model>], comma-separated)",
38668
+ parse: (args) => normalizeRuntimeShortlistInput(args.join(" ").split(",").map((entry) => entry.trim()).filter(Boolean)),
38669
+ resolveGet: (config) => (config.runtimeShortlist ?? []).join(", "),
38670
+ formatSummary: (config) => (config.runtimeShortlist ?? []).join(", ") || "—",
38671
+ formatValue: (value) => Array.isArray(value) ? value.join(", ") : "",
38672
+ apply: (config, value) => {
38673
+ const specs = normalizeRuntimeShortlistInput(value);
38674
+ if (specs.length === 0) {
38675
+ clearConfigValue(config, "runtimeShortlist");
38676
+ } else {
38677
+ setConfigValue(config, "runtimeShortlist", specs);
38678
+ }
38679
+ },
38680
+ clear: (config) => clearConfigValue(config, "runtimeShortlist")
38681
+ },
38682
+ {
38683
+ id: "runtime-presets",
38684
+ key: "runtimePresets",
38685
+ label: "Runtime presets",
38686
+ kind: "string-list",
38687
+ summary: "Named runtime tuples: id[:Label]=<harness>[/<model>[/<effort>]], comma-separated",
38688
+ parse: (args) => normalizeRuntimePresetsInput(args.join(" ").split(",").map((entry) => entry.trim()).filter(Boolean)),
38689
+ resolveGet: (config) => (config.runtimePresets ?? []).map(formatRuntimePresetSetting).join(", "),
38690
+ formatSummary: (config) => (config.runtimePresets ?? []).map(formatRuntimePresetSetting).join(", ") || "—",
38691
+ formatValue: (value) => Array.isArray(value) ? value.map(formatRuntimePresetSetting).join(", ") : "",
38692
+ apply: (config, value) => {
38693
+ const presets = normalizeRuntimePresetsInput(value);
38694
+ if (presets.length === 0) {
38695
+ clearConfigValue(config, "runtimePresets");
38696
+ } else {
38697
+ setConfigValue(config, "runtimePresets", presets);
38698
+ }
38699
+ },
38700
+ clear: (config) => clearConfigValue(config, "runtimePresets")
38179
38701
  }
38180
38702
  ];
38181
38703
  var USER_CONFIG_FIELD_INDEX = new Map(USER_CONFIG_FIELDS.flatMap((field) => [
@@ -38414,6 +38936,40 @@ class ThreadEventPlane {
38414
38936
  watch.clients.clear();
38415
38937
  }
38416
38938
  }
38939
+ // ../runtime/dist/mobile-push-seal.js
38940
+ var SALT = Buffer.from("openscout.push.v1", "utf8");
38941
+ var PKCS8_X25519_PREFIX = Buffer.from("302e020100300506032b656e04220420", "hex");
38942
+ var SPKI_X25519_PREFIX = Buffer.from("302a300506032b656e032100", "hex");
38943
+ var NONCE_BYTES = 12;
38944
+ var HEADER_BYTES = 1 + 32 + NONCE_BYTES;
38945
+ // ../runtime/dist/continuation/decide.js
38946
+ var WORKSPACE_COMMAND = new RegExp([
38947
+ "^(?:bun|npm|pnpm|yarn)\\s+(?:test|run\\s+[\\w:.-]+|lint|typecheck|check|build)(?:\\s|$)",
38948
+ "^(?:bunx|npx)\\s+tsc(?:\\s|$)",
38949
+ "^(?:cargo|go|swift)\\s+(?:test|build|check|vet)(?:\\s|$)",
38950
+ "^(?:pytest|tsc|make)(?:\\s|$)",
38951
+ "^(?:ls|pwd|cat|head|tail|wc|grep|rg)(?:\\s|$)",
38952
+ "^git\\s+(?:status|diff|log|show)(?:\\s|$)"
38953
+ ].join("|"));
38954
+ // ../runtime/dist/continuation/model.js
38955
+ var KINDS = new Set(["permission", "question", "plan", "hold", "unknown"]);
38956
+ var RISKS = new Set([
38957
+ "workspace",
38958
+ "network",
38959
+ "publish",
38960
+ "destructive",
38961
+ "secrets",
38962
+ "identity",
38963
+ "unknown"
38964
+ ]);
38965
+ var SYSTEM_PROMPT = [
38966
+ "Classify a coding-agent terminal dialog. Reply with JSON only:",
38967
+ '{"kind":"permission|question|plan|hold|unknown","command":string|null,"risk":"workspace|network|publish|destructive|secrets|identity|unknown","allowIndex":number|null,"confidence":"high|low","reason":string}',
38968
+ "kind=permission only for a Yes/No tool approval, not a question or plan.",
38969
+ "allowIndex is the numbered allow-once option (Yes). Never pick don't-ask-again or always-allow.",
38970
+ "risk=workspace for local tests/builds/edits. network for curl/http. publish for git push. destructive for rm -r/sudo. secrets for .env/keys.",
38971
+ "If unsure, confidence=low and kind=unknown."
38972
+ ].join(" ");
38417
38973
  // ../runtime/dist/activity-transitions.js
38418
38974
  class ActivityTransitionTracker {
38419
38975
  transitions = new Map;