runwork 0.26.0 → 0.27.0

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.
Files changed (2) hide show
  1. package/dist/index.js +1136 -477
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8205,7 +8205,7 @@ function createKeyboardListener() {
8205
8205
  }
8206
8206
 
8207
8207
  // src/generated/version.ts
8208
- var VERSION = "0.26.0";
8208
+ var VERSION = "0.27.0";
8209
8209
 
8210
8210
  // src/commands/dev.ts
8211
8211
  var exports_dev = {};
@@ -9184,6 +9184,14 @@ function expandWindowsPathTemplate(path2, resolved) {
9184
9184
  }
9185
9185
  return { path: path2, needsHomeJoin: !/^([A-Za-z]:[\\/]|\\\\|\/)/.test(path2) };
9186
9186
  }
9187
+ function parseConfigDeclaredPath(text2, key) {
9188
+ const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9189
+ const match = new RegExp(`^\\s*${escapedKey}\\s*=\\s*"((?:[^"\\\\]|\\\\.)*)"`, "m").exec(text2);
9190
+ if (!match)
9191
+ return null;
9192
+ const path2 = match[1].replace(/\\(.)/g, "$1");
9193
+ return path2 || null;
9194
+ }
9187
9195
  var PATH_REFRESH_FAILED_MARKER = "__runwork_path_refresh_failed__", WINDOWS_PATH_REFRESH, COMMAND_NOT_FOUND_EXIT_CODES, WINDOWS_PATH_PLACEHOLDERS;
9188
9196
  var init_detection_probes = __esm(() => {
9189
9197
  WINDOWS_PATH_REFRESH = "try { $env:Path = [Environment]::GetEnvironmentVariable('Path','Machine') + ';' + " + "[Environment]::GetEnvironmentVariable('Path','User') + ';' + $env:Path } " + `catch { Write-Output '${PATH_REFRESH_FAILED_MARKER}' }; `;
@@ -9605,6 +9613,9 @@ function getAgent(slug) {
9605
9613
  function getAgents() {
9606
9614
  return AGENT_REGISTRY;
9607
9615
  }
9616
+ function getDetectableAgents() {
9617
+ return AGENT_REGISTRY.filter((a) => a.detection);
9618
+ }
9608
9619
  function isConnectOnlyAgent(agent) {
9609
9620
  if (!agent)
9610
9621
  return false;
@@ -9633,11 +9644,15 @@ function resolveAgentCli(agent) {
9633
9644
  return;
9634
9645
  return detectionBinaryTarget(agent.detection);
9635
9646
  }
9636
- var CLAUDE_CODE_NATIVE_INSTALL_PATHS, CHATGPT_SECURITY_SETTINGS_URL = "https://chatgpt.com/plugins#settings/Security", CHATGPT_CREATE_CONNECTOR_URL = "https://chatgpt.com/plugins#settings/Connectors?create-connector=true&redirectAfter=%2Fplugins", AGENT_REGISTRY, slugIndex, nameIndex, CUSTOM_ADAPTER_SLUGS, getRegistryAgent, getRegistryAgents;
9647
+ var CLAUDE_CODE_NATIVE_INSTALL_PATHS, CODEX_CONFIG_FILE = ".codex/config.toml", CODEX_BUNDLED_CLI_PATHS, CHATGPT_SECURITY_SETTINGS_URL = "https://chatgpt.com/plugins#settings/Security", CHATGPT_CREATE_CONNECTOR_URL = "https://chatgpt.com/plugins#settings/Connectors?create-connector=true&redirectAfter=%2Fplugins", AGENT_REGISTRY, slugIndex, nameIndex, CUSTOM_ADAPTER_SLUGS, getRegistryAgent, getRegistryAgents;
9637
9648
  var init_registry_data = __esm(() => {
9638
9649
  CLAUDE_CODE_NATIVE_INSTALL_PATHS = [
9639
9650
  { macos: ".local/bin/claude", linux: ".local/bin/claude", windows: ".local/bin/claude.exe" }
9640
9651
  ];
9652
+ CODEX_BUNDLED_CLI_PATHS = [
9653
+ { macos: "/Applications/ChatGPT.app/Contents/Resources/codex" },
9654
+ { macos: "/Applications/Codex.app/Contents/Resources/codex" }
9655
+ ];
9641
9656
  AGENT_REGISTRY = [
9642
9657
  {
9643
9658
  slug: "claude-code",
@@ -9869,8 +9884,18 @@ var init_registry_data = __esm(() => {
9869
9884
  name: "Codex CLI",
9870
9885
  description: "AI in your terminal by OpenAI, great for coding, debugging, and automating dev tasks",
9871
9886
  category: "cli",
9872
- detection: { method: "binary", target: "codex" },
9873
- launch: { cli: "codex", cliAcceptsPrompt: true },
9887
+ detection: {
9888
+ method: "any",
9889
+ target: [
9890
+ { method: "binary", target: "codex" },
9891
+ {
9892
+ method: "config-value",
9893
+ target: { file: CODEX_CONFIG_FILE, key: "CODEX_CLI_PATH" }
9894
+ },
9895
+ ...CODEX_BUNDLED_CLI_PATHS.map((target) => ({ method: "path", target }))
9896
+ ]
9897
+ },
9898
+ launch: { cli: "codex", cliAcceptsPrompt: true, cliWellKnownPaths: CODEX_BUNDLED_CLI_PATHS },
9874
9899
  logo: "codex",
9875
9900
  downloadUrl: "https://learn.chatgpt.com/docs/codex/cli",
9876
9901
  install: {
@@ -9907,6 +9932,7 @@ var init_registry_data = __esm(() => {
9907
9932
  launch: { url: "https://chatgpt.com/?prompt={prompt}" },
9908
9933
  logo: "openai",
9909
9934
  downloadUrl: "https://chatgpt.com",
9935
+ suggestsCli: "codex",
9910
9936
  firstClass: true,
9911
9937
  resumeCapability: {
9912
9938
  mode: "url-prompt",
@@ -9963,6 +9989,7 @@ var init_registry_data = __esm(() => {
9963
9989
  ]
9964
9990
  },
9965
9991
  launch: { app: { macos: "ChatGPT Classic", windows: "ChatGPT Classic" }, bundleId: { macos: "com.openai.chat" }, appxPackage: "OpenAI.ChatGPT", url: "https://chatgpt.com/?prompt={prompt}" },
9992
+ suggestsCli: "codex",
9966
9993
  logo: "openai",
9967
9994
  downloadUrl: "https://chatgpt.com/download",
9968
9995
  downloadUrls: {
@@ -10208,12 +10235,145 @@ var init_registry_data = __esm(() => {
10208
10235
  getRegistryAgents = getAgents;
10209
10236
  });
10210
10237
 
10238
+ // src/agents/detection.ts
10239
+ import { execFile } from "child_process";
10240
+ import { existsSync as existsSync26, readFileSync as readFileSync23 } from "fs";
10241
+ import { homedir as homedir6, platform as platform2 } from "os";
10242
+ import { join as join22 } from "path";
10243
+ import { promisify } from "util";
10244
+ function isWindows() {
10245
+ return platform2() === "win32";
10246
+ }
10247
+ function toList(value) {
10248
+ return Array.isArray(value) ? value : [value];
10249
+ }
10250
+ async function runPowerShell(script) {
10251
+ const execFileAsync = promisify(execFile);
10252
+ try {
10253
+ await execFileAsync("powershell", ["-NoProfile", "-Command", script]);
10254
+ return true;
10255
+ } catch {
10256
+ return false;
10257
+ }
10258
+ }
10259
+ function resolveDetectionPath(target) {
10260
+ const resolved = resolvePlatformString(target);
10261
+ if (!resolved)
10262
+ return null;
10263
+ const expanded = expandWindowsPathTemplate(resolved, {
10264
+ "%APPDATA%": process.env.APPDATA,
10265
+ "%LOCALAPPDATA%": process.env.LOCALAPPDATA,
10266
+ "%ProgramFiles%": process.env.ProgramFiles
10267
+ });
10268
+ return expanded.needsHomeJoin ? join22(homedir6(), expanded.path) : expanded.path;
10269
+ }
10270
+ function checkPath(target) {
10271
+ const absolute = resolveDetectionPath(target);
10272
+ if (!absolute)
10273
+ return null;
10274
+ return existsSync26(absolute) ? absolute : null;
10275
+ }
10276
+ function checkConfigDeclaredPath(target) {
10277
+ const configPath = resolveDetectionPath(target.file);
10278
+ if (!configPath)
10279
+ return null;
10280
+ let text2;
10281
+ try {
10282
+ if (!existsSync26(configPath))
10283
+ return null;
10284
+ text2 = readFileSync23(configPath, "utf-8");
10285
+ } catch {
10286
+ return null;
10287
+ }
10288
+ const declared = parseConfigDeclaredPath(text2, target.key);
10289
+ return declared && existsSync26(declared) ? declared : null;
10290
+ }
10291
+ async function checkMacosBundleId(target) {
10292
+ if (platform2() !== "darwin")
10293
+ return false;
10294
+ const execFileAsync = promisify(execFile);
10295
+ for (const id of toList(target)) {
10296
+ if (!isValidBundleId(id))
10297
+ continue;
10298
+ try {
10299
+ await execFileAsync("sh", ["-c", macosBundleIdProbeScript(id)]);
10300
+ return true;
10301
+ } catch {}
10302
+ }
10303
+ return false;
10304
+ }
10305
+ async function checkWindowsAppxPackage(target) {
10306
+ if (!isWindows())
10307
+ return false;
10308
+ const probes = toList(target).map((pkg) => runPowerShell(appxPackageProbeScript(pkg)));
10309
+ const results = await Promise.all(probes);
10310
+ return results.some(Boolean);
10311
+ }
10312
+ async function checkWindowsStartApp(target) {
10313
+ if (!isWindows())
10314
+ return false;
10315
+ const probes = toList(target).map((pattern) => runPowerShell(startAppProbeScript(pattern)));
10316
+ const results = await Promise.all(probes);
10317
+ return results.some(Boolean);
10318
+ }
10319
+ async function runAgentDetectionDetailed(detection) {
10320
+ switch (detection.method) {
10321
+ case "binary": {
10322
+ const target = resolvePlatformString(detection.target);
10323
+ const resolved = target ? whichBinary(target) : null;
10324
+ return resolved ? { detected: true, via: "binary", resolvedPath: resolved } : NOT_DETECTED;
10325
+ }
10326
+ case "path": {
10327
+ const resolved = checkPath(detection.target);
10328
+ return resolved ? { detected: true, via: "path", resolvedPath: resolved } : NOT_DETECTED;
10329
+ }
10330
+ case "config-value": {
10331
+ const resolved = checkConfigDeclaredPath(detection.target);
10332
+ return resolved ? { detected: true, via: "config-value", resolvedPath: resolved } : NOT_DETECTED;
10333
+ }
10334
+ case "windows-appx":
10335
+ return await checkWindowsAppxPackage(detection.target) ? { detected: true, via: "windows-appx" } : NOT_DETECTED;
10336
+ case "windows-start-app":
10337
+ return await checkWindowsStartApp(detection.target) ? { detected: true, via: "windows-start-app" } : NOT_DETECTED;
10338
+ case "macos-bundle-id":
10339
+ return await checkMacosBundleId(detection.target) ? { detected: true, via: "macos-bundle-id" } : NOT_DETECTED;
10340
+ case "any": {
10341
+ const probes = await Promise.all(detection.target.map((p) => runAgentDetectionDetailed(p)));
10342
+ return probes.find((p) => p.detected) ?? NOT_DETECTED;
10343
+ }
10344
+ case "always":
10345
+ return { detected: true, via: "always" };
10346
+ default:
10347
+ return NOT_DETECTED;
10348
+ }
10349
+ }
10350
+ async function runAgentDetection(detection) {
10351
+ return (await runAgentDetectionDetailed(detection)).detected;
10352
+ }
10353
+
10354
+ class RegistryDetectedAdapter {
10355
+ async detect() {
10356
+ const def = getRegistryAgent(this.slug);
10357
+ if (!def)
10358
+ return false;
10359
+ return runAgentDetection(def.detection);
10360
+ }
10361
+ }
10362
+ var NOT_DETECTED;
10363
+ var init_detection = __esm(() => {
10364
+ init_which();
10365
+ init_registry_data();
10366
+ init_registry();
10367
+ init_detection_probes();
10368
+ NOT_DETECTED = { detected: false };
10369
+ });
10370
+
10211
10371
  // src/agents/registry.ts
10212
- import { platform as platform2, homedir as homedir6 } from "os";
10213
- import { isAbsolute as isAbsolute2, join as join22 } from "path";
10214
- import { existsSync as existsSync26 } from "fs";
10372
+ import { platform as platform3, homedir as homedir7 } from "os";
10373
+ import { isAbsolute as isAbsolute3, join as join23 } from "path";
10374
+ import { existsSync as existsSync27 } from "fs";
10215
10375
  function getNodePlatform() {
10216
- const p = platform2();
10376
+ const p = platform3();
10217
10377
  if (p === "darwin")
10218
10378
  return "macos";
10219
10379
  if (p === "win32")
@@ -10230,7 +10390,7 @@ function resolveToAbsolute(ps, scope) {
10230
10390
  const resolved = resolvePlatformString(ps);
10231
10391
  if (!resolved)
10232
10392
  return;
10233
- return scope === "global" ? join22(homedir6(), resolved) : join22(process.cwd(), resolved);
10393
+ return scope === "global" ? join23(homedir7(), resolved) : join23(process.cwd(), resolved);
10234
10394
  }
10235
10395
  function resolveAgentCliCommand(slug) {
10236
10396
  const agent = getAgent(slug);
@@ -10239,19 +10399,40 @@ function resolveAgentCliCommand(slug) {
10239
10399
  return null;
10240
10400
  if (whichBinary(cli))
10241
10401
  return cli;
10402
+ const declared = vendorDeclaredCliPath(slug);
10403
+ if (declared)
10404
+ return declared;
10242
10405
  for (const candidate of agent?.launch?.cliWellKnownPaths ?? []) {
10243
10406
  const resolved = resolvePlatformString(candidate);
10244
10407
  if (!resolved)
10245
10408
  continue;
10246
- const absolute = isAbsolute2(resolved) ? resolved : join22(homedir6(), resolved);
10247
- if (existsSync26(absolute))
10409
+ const absolute = isAbsolute3(resolved) ? resolved : join23(homedir7(), resolved);
10410
+ if (existsSync27(absolute))
10248
10411
  return absolute;
10249
10412
  }
10250
10413
  return null;
10251
10414
  }
10415
+ function configValueMatchers(detection) {
10416
+ if (!detection)
10417
+ return [];
10418
+ if (detection.method === "config-value")
10419
+ return [detection.target];
10420
+ if (detection.method === "any")
10421
+ return detection.target.flatMap(configValueMatchers);
10422
+ return [];
10423
+ }
10424
+ function vendorDeclaredCliPath(slug) {
10425
+ for (const matcher of configValueMatchers(getAgent(slug)?.detection)) {
10426
+ const resolved = checkConfigDeclaredPath(matcher);
10427
+ if (resolved)
10428
+ return resolved;
10429
+ }
10430
+ return null;
10431
+ }
10252
10432
  var init_registry = __esm(() => {
10253
10433
  init_which();
10254
10434
  init_registry_data();
10435
+ init_detection();
10255
10436
  init_registry_data();
10256
10437
  });
10257
10438
 
@@ -11092,6 +11273,8 @@ function scanClaudeJsonlHead(head) {
11092
11273
  result.firstTimestamp = o.timestamp;
11093
11274
  if (!result.cwd && typeof o.cwd === "string")
11094
11275
  result.cwd = o.cwd;
11276
+ if (!result.surface && typeof o.entrypoint === "string")
11277
+ result.surface = o.entrypoint;
11095
11278
  if (!result.title && o.type === "ai-title" && typeof o.aiTitle === "string") {
11096
11279
  result.title = titleFromText(o.aiTitle);
11097
11280
  }
@@ -11117,7 +11300,7 @@ function scanClaudeJsonlHead(head) {
11117
11300
  }
11118
11301
  }
11119
11302
  }
11120
- if (result.title && result.firstTimestamp && result.cwd)
11303
+ if (result.title && result.firstTimestamp && result.cwd && result.surface)
11121
11304
  break;
11122
11305
  }
11123
11306
  if (!result.title && firstUserText)
@@ -11146,6 +11329,8 @@ function scanCodexRolloutHead(head) {
11146
11329
  result.cwd = p.cwd;
11147
11330
  if (typeof p.id === "string" && !result.sessionId)
11148
11331
  result.sessionId = p.id;
11332
+ if (typeof p.originator === "string" && !result.surface)
11333
+ result.surface = p.originator;
11149
11334
  }
11150
11335
  if (!result.title && o.type === "response_item" && p.type === "message" && p.role === "user" && Array.isArray(p.content)) {
11151
11336
  for (const item of p.content) {
@@ -11245,23 +11430,23 @@ function skillNameFromPath(path2) {
11245
11430
  }
11246
11431
 
11247
11432
  // src/utils/trash.ts
11248
- import { cpSync, existsSync as existsSync27, mkdirSync as mkdirSync13, readdirSync as readdirSync5, renameSync as renameSync3, rmSync as rmSync4, statSync as statSync3 } from "fs";
11249
- import { basename as basename2, dirname as dirname6, join as join23 } from "path";
11250
- import { homedir as homedir7 } from "os";
11433
+ import { cpSync, existsSync as existsSync28, mkdirSync as mkdirSync13, readdirSync as readdirSync5, renameSync as renameSync3, rmSync as rmSync4, statSync as statSync3 } from "fs";
11434
+ import { basename as basename2, dirname as dirname6, join as join24 } from "path";
11435
+ import { homedir as homedir8 } from "os";
11251
11436
  function trashRoot() {
11252
- return join23(homedir7(), ".runwork", "trash");
11437
+ return join24(homedir8(), ".runwork", "trash");
11253
11438
  }
11254
11439
  function batchDir(now) {
11255
11440
  const stamp = now.toISOString().replace(/[:.]/g, "-");
11256
- return join23(trashRoot(), `${stamp}-${process.pid}`);
11441
+ return join24(trashRoot(), `${stamp}-${process.pid}`);
11257
11442
  }
11258
11443
  function pruneTrash(now = new Date) {
11259
11444
  const root = trashRoot();
11260
- if (!existsSync27(root))
11445
+ if (!existsSync28(root))
11261
11446
  return;
11262
11447
  const cutoff = now.getTime() - TRASH_RETENTION_DAYS * 24 * 60 * 60 * 1000;
11263
11448
  for (const entry of readdirSync5(root)) {
11264
- const dir = join23(root, entry);
11449
+ const dir = join24(root, entry);
11265
11450
  try {
11266
11451
  if (statSync3(dir).mtimeMs < cutoff)
11267
11452
  rmSync4(dir, { recursive: true, force: true });
@@ -11269,7 +11454,7 @@ function pruneTrash(now = new Date) {
11269
11454
  }
11270
11455
  }
11271
11456
  function moveToTrash(sourcePath, reason, now = new Date) {
11272
- if (!existsSync27(sourcePath))
11457
+ if (!existsSync28(sourcePath))
11273
11458
  return null;
11274
11459
  if (!activeBatch || !activeBatch.startsWith(trashRoot())) {
11275
11460
  activeBatch = batchDir(now);
@@ -11277,8 +11462,8 @@ function moveToTrash(sourcePath, reason, now = new Date) {
11277
11462
  }
11278
11463
  const parent = basename2(dirname6(sourcePath));
11279
11464
  const grandparent = basename2(dirname6(dirname6(sourcePath)));
11280
- const destDir = join23(activeBatch, `${grandparent}__${parent}`.replace(/[^a-zA-Z0-9._-]/g, "-"));
11281
- const dest = join23(destDir, basename2(sourcePath));
11465
+ const destDir = join24(activeBatch, `${grandparent}__${parent}`.replace(/[^a-zA-Z0-9._-]/g, "-"));
11466
+ const dest = join24(destDir, basename2(sourcePath));
11282
11467
  try {
11283
11468
  mkdirSync13(destDir, { recursive: true });
11284
11469
  try {
@@ -11290,7 +11475,7 @@ function moveToTrash(sourcePath, reason, now = new Date) {
11290
11475
  } catch {
11291
11476
  return null;
11292
11477
  }
11293
- const manifestPath = join23(activeBatch, "manifest.json");
11478
+ const manifestPath = join24(activeBatch, "manifest.json");
11294
11479
  const manifest = readJsonOrNull(manifestPath) ?? { entries: [] };
11295
11480
  manifest.entries.push({ from: sourcePath, to: dest, reason, at: now.toISOString() });
11296
11481
  try {
@@ -11333,27 +11518,27 @@ function configHash(value) {
11333
11518
  var init_hash = () => {};
11334
11519
 
11335
11520
  // src/agents/utils/json-config.ts
11336
- import { readFileSync as readFileSync23, writeFileSync as writeFileSync14, mkdirSync as mkdirSync14, existsSync as existsSync28 } from "fs";
11521
+ import { readFileSync as readFileSync24, writeFileSync as writeFileSync14, mkdirSync as mkdirSync14, existsSync as existsSync29 } from "fs";
11337
11522
  import { dirname as dirname7 } from "path";
11338
11523
  function isRunworkManagedKey(key) {
11339
11524
  return key === RUNWORK_WORKSPACE_MCP_NAME || key.startsWith(RUNWORK_MCP_PREFIX) || key.startsWith(RUNWORK_MCP_PREFIX_LEGACY);
11340
11525
  }
11341
11526
  function readJsonConfig(filePath) {
11342
- if (!existsSync28(filePath))
11527
+ if (!existsSync29(filePath))
11343
11528
  return {};
11344
11529
  try {
11345
- return JSON.parse(readFileSync23(filePath, "utf-8"));
11530
+ return JSON.parse(readFileSync24(filePath, "utf-8"));
11346
11531
  } catch (err) {
11347
11532
  console.warn(` [config] ${filePath} is not valid JSON: ${err instanceof Error ? err.message : err}`);
11348
11533
  return {};
11349
11534
  }
11350
11535
  }
11351
11536
  function existingContentIsUnparseable(filePath) {
11352
- if (!existsSync28(filePath))
11537
+ if (!existsSync29(filePath))
11353
11538
  return { bad: false };
11354
11539
  let raw;
11355
11540
  try {
11356
- raw = readFileSync23(filePath, "utf-8");
11541
+ raw = readFileSync24(filePath, "utf-8");
11357
11542
  } catch {
11358
11543
  return { bad: false };
11359
11544
  }
@@ -11375,7 +11560,7 @@ function writeJsonConfig(filePath, config) {
11375
11560
  `);
11376
11561
  }
11377
11562
  function removeRunworkMcpServers(filePath, topKey) {
11378
- if (!existsSync28(filePath))
11563
+ if (!existsSync29(filePath))
11379
11564
  return false;
11380
11565
  const config = readJsonConfig(filePath);
11381
11566
  const existing = config[topKey] || {};
@@ -11430,25 +11615,25 @@ var init_json_config = __esm(() => {
11430
11615
  });
11431
11616
 
11432
11617
  // src/agents/utils/skill-removal.ts
11433
- import { existsSync as existsSync29, readdirSync as readdirSync6 } from "fs";
11434
- import { join as join24 } from "path";
11618
+ import { existsSync as existsSync30, readdirSync as readdirSync6 } from "fs";
11619
+ import { join as join25 } from "path";
11435
11620
  function removeMatchingSkillDirs(dir, allowed, reason = "skill removed") {
11436
- if (!allowed.size || !existsSync29(dir))
11621
+ if (!allowed.size || !existsSync30(dir))
11437
11622
  return;
11438
11623
  for (const entry of readdirSync6(dir)) {
11439
11624
  if (!allowed.has(entry))
11440
11625
  continue;
11441
- moveToTrash(join24(dir, entry), reason);
11626
+ moveToTrash(join25(dir, entry), reason);
11442
11627
  }
11443
11628
  }
11444
11629
  function removeMatchingSkillFiles(dir, allowed, suffix, reason = "skill removed") {
11445
- if (!allowed.size || !existsSync29(dir))
11630
+ if (!allowed.size || !existsSync30(dir))
11446
11631
  return;
11447
11632
  const names = new Set([...allowed].map((slug) => `${slug}${suffix}`));
11448
11633
  for (const entry of readdirSync6(dir)) {
11449
11634
  if (!names.has(entry))
11450
11635
  continue;
11451
- moveToTrash(join24(dir, entry), reason);
11636
+ moveToTrash(join25(dir, entry), reason);
11452
11637
  }
11453
11638
  }
11454
11639
  var init_skill_removal = __esm(() => {
@@ -11456,7 +11641,7 @@ var init_skill_removal = __esm(() => {
11456
11641
  });
11457
11642
 
11458
11643
  // src/agents/utils/instruction-hint.ts
11459
- import { existsSync as existsSync30, readFileSync as readFileSync24, writeFileSync as writeFileSync15, mkdirSync as mkdirSync15 } from "fs";
11644
+ import { existsSync as existsSync31, readFileSync as readFileSync25, writeFileSync as writeFileSync15, mkdirSync as mkdirSync15 } from "fs";
11460
11645
  import { dirname as dirname8 } from "path";
11461
11646
  function writeHintToFile(filePath, hint) {
11462
11647
  mkdirSync15(dirname8(filePath), { recursive: true });
@@ -11466,8 +11651,8 @@ ${hint}
11466
11651
  ${END_MARKER}`;
11467
11652
  }
11468
11653
  let content = "";
11469
- if (existsSync30(filePath)) {
11470
- content = readFileSync24(filePath, "utf-8");
11654
+ if (existsSync31(filePath)) {
11655
+ content = readFileSync25(filePath, "utf-8");
11471
11656
  }
11472
11657
  const startIdx = content.indexOf(START_MARKER);
11473
11658
  const endIdx = content.indexOf(END_MARKER);
@@ -11489,9 +11674,9 @@ ${END_MARKER}`;
11489
11674
  writeFileSync15(filePath, content);
11490
11675
  }
11491
11676
  function removeHintFromFile(filePath) {
11492
- if (!existsSync30(filePath))
11677
+ if (!existsSync31(filePath))
11493
11678
  return false;
11494
- let content = readFileSync24(filePath, "utf-8");
11679
+ let content = readFileSync25(filePath, "utf-8");
11495
11680
  const startIdx = content.indexOf(START_MARKER);
11496
11681
  const endIdx = content.indexOf(END_MARKER);
11497
11682
  if (startIdx < 0 || endIdx < 0)
@@ -11509,9 +11694,9 @@ function removeHintFromFile(filePath) {
11509
11694
  return true;
11510
11695
  }
11511
11696
  function removeTeamInstructionsFromFile(filePath) {
11512
- if (!existsSync30(filePath))
11697
+ if (!existsSync31(filePath))
11513
11698
  return false;
11514
- let content = readFileSync24(filePath, "utf-8");
11699
+ let content = readFileSync25(filePath, "utf-8");
11515
11700
  const startIdx = content.indexOf(TEAM_START_MARKER);
11516
11701
  const endIdx = content.indexOf(TEAM_END_MARKER);
11517
11702
  if (startIdx < 0 || endIdx < 0)
@@ -11531,8 +11716,8 @@ function removeTeamInstructionsFromFile(filePath) {
11531
11716
  function writeTeamInstructionsToFile(filePath, instructions) {
11532
11717
  mkdirSync15(dirname8(filePath), { recursive: true });
11533
11718
  let content = "";
11534
- if (existsSync30(filePath)) {
11535
- content = readFileSync24(filePath, "utf-8");
11719
+ if (existsSync31(filePath)) {
11720
+ content = readFileSync25(filePath, "utf-8");
11536
11721
  }
11537
11722
  const block = `${TEAM_START_MARKER}
11538
11723
  ${instructions}
@@ -11981,120 +12166,6 @@ function vlog(...args) {
11981
12166
  }
11982
12167
  var verbose = false;
11983
12168
 
11984
- // src/agents/detection.ts
11985
- import { execFile } from "child_process";
11986
- import { existsSync as existsSync31 } from "fs";
11987
- import { homedir as homedir8, platform as platform3 } from "os";
11988
- import { join as join25 } from "path";
11989
- import { promisify } from "util";
11990
- function isWindows() {
11991
- return platform3() === "win32";
11992
- }
11993
- function toList(value) {
11994
- return Array.isArray(value) ? value : [value];
11995
- }
11996
- async function runPowerShell(script) {
11997
- const execFileAsync = promisify(execFile);
11998
- try {
11999
- await execFileAsync("powershell", ["-NoProfile", "-Command", script]);
12000
- return true;
12001
- } catch {
12002
- return false;
12003
- }
12004
- }
12005
- function resolveDetectionPath(target) {
12006
- const resolved = resolvePlatformString(target);
12007
- if (!resolved)
12008
- return null;
12009
- const expanded = expandWindowsPathTemplate(resolved, {
12010
- "%APPDATA%": process.env.APPDATA,
12011
- "%LOCALAPPDATA%": process.env.LOCALAPPDATA,
12012
- "%ProgramFiles%": process.env.ProgramFiles
12013
- });
12014
- return expanded.needsHomeJoin ? join25(homedir8(), expanded.path) : expanded.path;
12015
- }
12016
- function checkPath(target) {
12017
- const absolute = resolveDetectionPath(target);
12018
- if (!absolute)
12019
- return null;
12020
- return existsSync31(absolute) ? absolute : null;
12021
- }
12022
- async function checkMacosBundleId(target) {
12023
- if (platform3() !== "darwin")
12024
- return false;
12025
- const execFileAsync = promisify(execFile);
12026
- for (const id of toList(target)) {
12027
- if (!isValidBundleId(id))
12028
- continue;
12029
- try {
12030
- await execFileAsync("sh", ["-c", macosBundleIdProbeScript(id)]);
12031
- return true;
12032
- } catch {}
12033
- }
12034
- return false;
12035
- }
12036
- async function checkWindowsAppxPackage(target) {
12037
- if (!isWindows())
12038
- return false;
12039
- const probes = toList(target).map((pkg) => runPowerShell(appxPackageProbeScript(pkg)));
12040
- const results = await Promise.all(probes);
12041
- return results.some(Boolean);
12042
- }
12043
- async function checkWindowsStartApp(target) {
12044
- if (!isWindows())
12045
- return false;
12046
- const probes = toList(target).map((pattern) => runPowerShell(startAppProbeScript(pattern)));
12047
- const results = await Promise.all(probes);
12048
- return results.some(Boolean);
12049
- }
12050
- async function runAgentDetectionDetailed(detection) {
12051
- switch (detection.method) {
12052
- case "binary": {
12053
- const target = resolvePlatformString(detection.target);
12054
- const resolved = target ? whichBinary(target) : null;
12055
- return resolved ? { detected: true, via: "binary", resolvedPath: resolved } : NOT_DETECTED;
12056
- }
12057
- case "path": {
12058
- const resolved = checkPath(detection.target);
12059
- return resolved ? { detected: true, via: "path", resolvedPath: resolved } : NOT_DETECTED;
12060
- }
12061
- case "windows-appx":
12062
- return await checkWindowsAppxPackage(detection.target) ? { detected: true, via: "windows-appx" } : NOT_DETECTED;
12063
- case "windows-start-app":
12064
- return await checkWindowsStartApp(detection.target) ? { detected: true, via: "windows-start-app" } : NOT_DETECTED;
12065
- case "macos-bundle-id":
12066
- return await checkMacosBundleId(detection.target) ? { detected: true, via: "macos-bundle-id" } : NOT_DETECTED;
12067
- case "any": {
12068
- const probes = await Promise.all(detection.target.map((p) => runAgentDetectionDetailed(p)));
12069
- return probes.find((p) => p.detected) ?? NOT_DETECTED;
12070
- }
12071
- case "always":
12072
- return { detected: true, via: "always" };
12073
- default:
12074
- return NOT_DETECTED;
12075
- }
12076
- }
12077
- async function runAgentDetection(detection) {
12078
- return (await runAgentDetectionDetailed(detection)).detected;
12079
- }
12080
-
12081
- class RegistryDetectedAdapter {
12082
- async detect() {
12083
- const def = getRegistryAgent(this.slug);
12084
- if (!def)
12085
- return false;
12086
- return runAgentDetection(def.detection);
12087
- }
12088
- }
12089
- var NOT_DETECTED;
12090
- var init_detection = __esm(() => {
12091
- init_which();
12092
- init_registry_data();
12093
- init_registry();
12094
- init_detection_probes();
12095
- NOT_DETECTED = { detected: false };
12096
- });
12097
-
12098
12169
  // src/agents/transcript-sources.ts
12099
12170
  import { accessSync, constants, statSync as statSync4 } from "fs";
12100
12171
  function classifyFsErrorCode(code) {
@@ -12158,7 +12229,7 @@ function summarizeTranscriptSources(sources) {
12158
12229
  var init_transcript_sources = () => {};
12159
12230
 
12160
12231
  // src/agents/claude-code.ts
12161
- import { chmodSync, existsSync as existsSync32, mkdirSync as mkdirSync16, readFileSync as readFileSync25, readdirSync as readdirSync7, rmSync as rmSync5, statSync as statSync5, writeFileSync as writeFileSync16 } from "fs";
12232
+ import { chmodSync, existsSync as existsSync32, mkdirSync as mkdirSync16, readFileSync as readFileSync26, readdirSync as readdirSync7, rmSync as rmSync5, statSync as statSync5, writeFileSync as writeFileSync16 } from "fs";
12162
12233
  import { join as join26 } from "path";
12163
12234
  import { homedir as homedir9 } from "os";
12164
12235
  function getPluginJson() {
@@ -12349,7 +12420,7 @@ ${instructions}`;
12349
12420
  let settings = {};
12350
12421
  if (hadFile) {
12351
12422
  try {
12352
- settings = JSON.parse(readFileSync25(settingsPath, "utf-8"));
12423
+ settings = JSON.parse(readFileSync26(settingsPath, "utf-8"));
12353
12424
  } catch {}
12354
12425
  }
12355
12426
  if (settings.permissions && typeof settings.permissions === "object") {
@@ -12410,7 +12481,7 @@ ${instructions}`;
12410
12481
  const settingsPath = join26(homedir9(), ".claude", "settings.json");
12411
12482
  if (existsSync32(settingsPath)) {
12412
12483
  try {
12413
- const settings = JSON.parse(readFileSync25(settingsPath, "utf-8"));
12484
+ const settings = JSON.parse(readFileSync26(settingsPath, "utf-8"));
12414
12485
  if (settings.permissions) {
12415
12486
  for (const key of ["allow", "deny"]) {
12416
12487
  const arr = settings.permissions[key];
@@ -12508,7 +12579,7 @@ ${instructions}`;
12508
12579
  continue;
12509
12580
  let content;
12510
12581
  try {
12511
- content = readFileSync25(filePath, "utf-8");
12582
+ content = readFileSync26(filePath, "utf-8");
12512
12583
  } catch {
12513
12584
  continue;
12514
12585
  }
@@ -12633,7 +12704,7 @@ ${instructions}`;
12633
12704
  continue;
12634
12705
  let content;
12635
12706
  try {
12636
- content = readFileSync25(filePath, "utf-8");
12707
+ content = readFileSync26(filePath, "utf-8");
12637
12708
  } catch {
12638
12709
  continue;
12639
12710
  }
@@ -12689,7 +12760,7 @@ ${instructions}`;
12689
12760
  const sessionId = file.slice(0, -".jsonl".length);
12690
12761
  let endedAt = null;
12691
12762
  try {
12692
- const stamp = JSON.parse(readFileSync25(join26(homedir9(), ".runwork", "sessions", `${sessionId}.ended.json`), "utf-8"));
12763
+ const stamp = JSON.parse(readFileSync26(join26(homedir9(), ".runwork", "sessions", `${sessionId}.ended.json`), "utf-8"));
12693
12764
  if (stamp && typeof stamp.endedAt === "string")
12694
12765
  endedAt = stamp.endedAt;
12695
12766
  } catch {}
@@ -12701,7 +12772,8 @@ ${instructions}`;
12701
12772
  startedAt: scanned.firstTimestamp,
12702
12773
  lastActivityAt: resolveLastActivity(filePath, stat.mtimeMs),
12703
12774
  endedAt,
12704
- transcriptPath: filePath
12775
+ transcriptPath: filePath,
12776
+ surface: scanned.surface ?? null
12705
12777
  });
12706
12778
  }
12707
12779
  }
@@ -12755,7 +12827,7 @@ ${instructions}`;
12755
12827
  continue;
12756
12828
  let content;
12757
12829
  try {
12758
- content = readFileSync25(filePath, "utf-8");
12830
+ content = readFileSync26(filePath, "utf-8");
12759
12831
  } catch {
12760
12832
  continue;
12761
12833
  }
@@ -13003,7 +13075,7 @@ var init_claude_desktop_plugin_tree = __esm(() => {
13003
13075
  });
13004
13076
 
13005
13077
  // src/agents/claude-desktop.ts
13006
- import { existsSync as existsSync34, mkdtempSync as mkdtempSync3, readdirSync as readdirSync8, readFileSync as readFileSync26, rmSync as rmSync7, statSync as statSync6, writeFileSync as writeFileSync18, mkdirSync as mkdirSync18 } from "fs";
13078
+ import { existsSync as existsSync34, mkdtempSync as mkdtempSync3, readdirSync as readdirSync8, readFileSync as readFileSync27, rmSync as rmSync7, statSync as statSync6, writeFileSync as writeFileSync18, mkdirSync as mkdirSync18 } from "fs";
13007
13079
  import { dirname as dirname9, join as join28 } from "path";
13008
13080
  import { homedir as homedir10, platform as platform4, tmpdir as tmpdir3 } from "os";
13009
13081
  function isRunworkRpmPluginName(name) {
@@ -13122,7 +13194,7 @@ function findRpmPluginByName(pluginName) {
13122
13194
  if (!existsSync34(manifestPath))
13123
13195
  return null;
13124
13196
  try {
13125
- const manifest = JSON.parse(readFileSync26(manifestPath, "utf-8"));
13197
+ const manifest = JSON.parse(readFileSync27(manifestPath, "utf-8"));
13126
13198
  const entry = manifest.plugins?.find((p) => p.name === pluginName);
13127
13199
  if (!entry?.id)
13128
13200
  return null;
@@ -13303,7 +13375,7 @@ var init_claude_desktop = __esm(() => {
13303
13375
  let desktopConfig = {};
13304
13376
  if (existsSync34(configPath)) {
13305
13377
  try {
13306
- desktopConfig = JSON.parse(readFileSync26(configPath, "utf-8"));
13378
+ desktopConfig = JSON.parse(readFileSync27(configPath, "utf-8"));
13307
13379
  } catch {}
13308
13380
  }
13309
13381
  if (!desktopConfig.preferences)
@@ -13342,7 +13414,7 @@ var init_claude_desktop = __esm(() => {
13342
13414
  if (!existsSync34(manifestPath))
13343
13415
  continue;
13344
13416
  try {
13345
- const manifest = JSON.parse(readFileSync26(manifestPath, "utf-8"));
13417
+ const manifest = JSON.parse(readFileSync27(manifestPath, "utf-8"));
13346
13418
  if (!Array.isArray(manifest.plugins))
13347
13419
  continue;
13348
13420
  const ours = manifest.plugins.filter((p) => isRunworkRpmPluginName(p.name));
@@ -13444,7 +13516,7 @@ var init_claude_desktop = __esm(() => {
13444
13516
  continue;
13445
13517
  let content;
13446
13518
  try {
13447
- content = readFileSync26(filePath, "utf-8");
13519
+ content = readFileSync27(filePath, "utf-8");
13448
13520
  } catch {
13449
13521
  continue;
13450
13522
  }
@@ -13484,7 +13556,7 @@ var init_claude_desktop = __esm(() => {
13484
13556
  const metaPath = join28(orgPath, entry);
13485
13557
  let meta;
13486
13558
  try {
13487
- meta = JSON.parse(readFileSync26(metaPath, "utf-8"));
13559
+ meta = JSON.parse(readFileSync27(metaPath, "utf-8"));
13488
13560
  } catch {
13489
13561
  continue;
13490
13562
  }
@@ -13520,7 +13592,8 @@ var init_claude_desktop = __esm(() => {
13520
13592
  title: typeof meta.title === "string" && meta.title ? meta.title : null,
13521
13593
  startedAt: typeof meta.createdAt === "number" ? new Date(meta.createdAt).toISOString() : null,
13522
13594
  lastActivityAt: new Date(lastActivityMs).toISOString(),
13523
- transcriptPath
13595
+ transcriptPath,
13596
+ surface: "local-agent"
13524
13597
  });
13525
13598
  }
13526
13599
  }
@@ -13586,7 +13659,7 @@ var init_claude_desktop = __esm(() => {
13586
13659
  const scheduledTasksPath = join28(claudeAppDir, "scheduled-tasks.json");
13587
13660
  if (existsSync34(scheduledTasksPath)) {
13588
13661
  try {
13589
- const raw = readFileSync26(scheduledTasksPath, "utf-8");
13662
+ const raw = readFileSync27(scheduledTasksPath, "utf-8");
13590
13663
  const parsed = JSON.parse(raw);
13591
13664
  const tasks = Array.isArray(parsed) ? parsed : Object.values(parsed);
13592
13665
  for (const task of tasks) {
@@ -13630,7 +13703,7 @@ var init_claude_desktop = __esm(() => {
13630
13703
  }
13631
13704
  const versionPath = join28(claudeAppDir, "claude-code", "sdk-version");
13632
13705
  if (existsSync34(versionPath)) {
13633
- return readFileSync26(versionPath, "utf-8").trim();
13706
+ return readFileSync27(versionPath, "utf-8").trim();
13634
13707
  }
13635
13708
  return null;
13636
13709
  } catch {
@@ -13663,7 +13736,7 @@ var init_claude_desktop = __esm(() => {
13663
13736
  if (!file.endsWith(".json"))
13664
13737
  continue;
13665
13738
  try {
13666
- const session = JSON.parse(readFileSync26(join28(userPath, file), "utf-8"));
13739
+ const session = JSON.parse(readFileSync27(join28(userPath, file), "utf-8"));
13667
13740
  onSession(session);
13668
13741
  } catch {
13669
13742
  continue;
@@ -14207,7 +14280,7 @@ ${hint}`;
14207
14280
  });
14208
14281
 
14209
14282
  // src/agents/codex.ts
14210
- import { existsSync as existsSync37, mkdirSync as mkdirSync21, readdirSync as readdirSync11, readFileSync as readFileSync27, statSync as statSync7, writeFileSync as writeFileSync21 } from "fs";
14283
+ import { existsSync as existsSync37, mkdirSync as mkdirSync21, readdirSync as readdirSync11, readFileSync as readFileSync28, statSync as statSync7, writeFileSync as writeFileSync21 } from "fs";
14211
14284
  import { basename as basename3, join as join31 } from "path";
14212
14285
  import { homedir as homedir13 } from "os";
14213
14286
  import { parse, stringify } from "smol-toml";
@@ -14240,7 +14313,7 @@ var init_codex = __esm(async () => {
14240
14313
  const configPath = join31(homedir13(), ".codex", "config.toml");
14241
14314
  let parsed = {};
14242
14315
  if (existsSync37(configPath)) {
14243
- parsed = parse(readFileSync27(configPath, "utf-8"));
14316
+ parsed = parse(readFileSync28(configPath, "utf-8"));
14244
14317
  }
14245
14318
  if (!parsed.mcp_servers || typeof parsed.mcp_servers !== "object") {
14246
14319
  parsed.mcp_servers = {};
@@ -14295,7 +14368,7 @@ var init_codex = __esm(async () => {
14295
14368
  const configPath = scope === "project" ? join31(process.cwd(), ".codex", "config.toml") : join31(homedir13(), ".codex", "config.toml");
14296
14369
  let parsed = {};
14297
14370
  if (existsSync37(configPath)) {
14298
- parsed = parse(readFileSync27(configPath, "utf-8"));
14371
+ parsed = parse(readFileSync28(configPath, "utf-8"));
14299
14372
  }
14300
14373
  if (config.modelPreference) {
14301
14374
  parsed.model = config.modelPreference;
@@ -14354,7 +14427,7 @@ var init_codex = __esm(async () => {
14354
14427
  const configPath = join31(homedir13(), ".codex", "config.toml");
14355
14428
  if (existsSync37(configPath)) {
14356
14429
  try {
14357
- const parsed = parse(readFileSync27(configPath, "utf-8"));
14430
+ const parsed = parse(readFileSync28(configPath, "utf-8"));
14358
14431
  if (parsed.mcp_servers && typeof parsed.mcp_servers === "object") {
14359
14432
  const mcpServers = parsed.mcp_servers;
14360
14433
  for (const key of Object.keys(mcpServers)) {
@@ -14403,7 +14476,7 @@ var init_codex = __esm(async () => {
14403
14476
  if (messageCount === 0) {
14404
14477
  const historyPath = join31(codexDir, "history.jsonl");
14405
14478
  if (existsSync37(historyPath)) {
14406
- const content = readFileSync27(historyPath, "utf-8").trim();
14479
+ const content = readFileSync28(historyPath, "utf-8").trim();
14407
14480
  if (content) {
14408
14481
  for (const line of content.split(/[\r\n]+/)) {
14409
14482
  try {
@@ -14483,7 +14556,7 @@ var init_codex = __esm(async () => {
14483
14556
  continue;
14484
14557
  let content;
14485
14558
  try {
14486
- content = readFileSync27(file, "utf-8");
14559
+ content = readFileSync28(file, "utf-8");
14487
14560
  } catch {
14488
14561
  continue;
14489
14562
  }
@@ -14575,7 +14648,7 @@ var init_codex = __esm(async () => {
14575
14648
  continue;
14576
14649
  let content;
14577
14650
  try {
14578
- content = readFileSync27(file, "utf-8");
14651
+ content = readFileSync28(file, "utf-8");
14579
14652
  } catch {
14580
14653
  continue;
14581
14654
  }
@@ -14634,7 +14707,8 @@ var init_codex = __esm(async () => {
14634
14707
  title: scanned.title,
14635
14708
  startedAt: scanned.firstTimestamp,
14636
14709
  lastActivityAt: resolveLastActivity(file, stat.mtimeMs),
14637
- transcriptPath: file
14710
+ transcriptPath: file,
14711
+ surface: scanned.surface ?? null
14638
14712
  });
14639
14713
  }
14640
14714
  return sessions;
@@ -14646,7 +14720,7 @@ var init_codex = __esm(async () => {
14646
14720
  try {
14647
14721
  const versionPath = join31(homedir13(), ".codex", "version.json");
14648
14722
  if (existsSync37(versionPath)) {
14649
- const data = JSON.parse(readFileSync27(versionPath, "utf-8"));
14723
+ const data = JSON.parse(readFileSync28(versionPath, "utf-8"));
14650
14724
  return data.latest_version ?? null;
14651
14725
  }
14652
14726
  } catch {}
@@ -14707,7 +14781,7 @@ var init_codex = __esm(async () => {
14707
14781
  parseRolloutForSkills(filePath, sinceMs, skillCounts) {
14708
14782
  let content;
14709
14783
  try {
14710
- content = readFileSync27(filePath, "utf-8");
14784
+ content = readFileSync28(filePath, "utf-8");
14711
14785
  } catch {
14712
14786
  return;
14713
14787
  }
@@ -14760,7 +14834,7 @@ var init_codex = __esm(async () => {
14760
14834
  let state = {};
14761
14835
  if (existsSync37(statePath)) {
14762
14836
  try {
14763
- state = JSON.parse(readFileSync27(statePath, "utf-8"));
14837
+ state = JSON.parse(readFileSync28(statePath, "utf-8"));
14764
14838
  } catch {
14765
14839
  return "app_running";
14766
14840
  }
@@ -14795,23 +14869,11 @@ var init_codex = __esm(async () => {
14795
14869
  CodexDesktopAdapter = class CodexDesktopAdapter extends CodexAdapter {
14796
14870
  name = "Codex";
14797
14871
  slug = "codex-app";
14798
- async readUsageStats() {
14799
- return null;
14800
- }
14801
- async listSessions() {
14802
- return null;
14803
- }
14804
- async readSessionDigests() {
14805
- return null;
14806
- }
14807
- transcriptSources() {
14808
- return [];
14809
- }
14810
14872
  };
14811
14873
  });
14812
14874
 
14813
14875
  // src/agents/cline.ts
14814
- import { existsSync as existsSync38, mkdirSync as mkdirSync22, readFileSync as readFileSync28, readdirSync as readdirSync12, rmSync as rmSync10, unlinkSync as unlinkSync6, writeFileSync as writeFileSync22 } from "fs";
14876
+ import { existsSync as existsSync38, mkdirSync as mkdirSync22, readFileSync as readFileSync29, readdirSync as readdirSync12, rmSync as rmSync10, unlinkSync as unlinkSync6, writeFileSync as writeFileSync22 } from "fs";
14815
14877
  import { join as join32 } from "path";
14816
14878
  import { homedir as homedir14 } from "os";
14817
14879
  var ClineAdapter;
@@ -14872,7 +14934,7 @@ var init_cline = __esm(() => {
14872
14934
  let state = {};
14873
14935
  if (existsSync38(globalStatePath)) {
14874
14936
  try {
14875
- state = JSON.parse(readFileSync28(globalStatePath, "utf-8"));
14937
+ state = JSON.parse(readFileSync29(globalStatePath, "utf-8"));
14876
14938
  } catch {}
14877
14939
  }
14878
14940
  if (config.modelPreference) {
@@ -14929,7 +14991,7 @@ var init_cline = __esm(() => {
14929
14991
  });
14930
14992
 
14931
14993
  // src/agents/gemini.ts
14932
- import { existsSync as existsSync39, mkdirSync as mkdirSync23, readdirSync as readdirSync13, readFileSync as readFileSync29, statSync as statSync8, writeFileSync as writeFileSync23 } from "fs";
14994
+ import { existsSync as existsSync39, mkdirSync as mkdirSync23, readdirSync as readdirSync13, readFileSync as readFileSync30, statSync as statSync8, writeFileSync as writeFileSync23 } from "fs";
14933
14995
  import { basename as basename4, join as join33 } from "path";
14934
14996
  import { homedir as homedir15 } from "os";
14935
14997
  var GeminiAdapter;
@@ -14989,7 +15051,7 @@ var init_gemini = __esm(() => {
14989
15051
  let settings = {};
14990
15052
  if (existsSync39(settingsPath)) {
14991
15053
  try {
14992
- settings = JSON.parse(readFileSync29(settingsPath, "utf-8"));
15054
+ settings = JSON.parse(readFileSync30(settingsPath, "utf-8"));
14993
15055
  } catch {}
14994
15056
  }
14995
15057
  if (config.modelPreference) {
@@ -15050,7 +15112,7 @@ var init_gemini = __esm(() => {
15050
15112
  continue;
15051
15113
  let session;
15052
15114
  try {
15053
- session = JSON.parse(readFileSync29(filePath, "utf-8"));
15115
+ session = JSON.parse(readFileSync30(filePath, "utf-8"));
15054
15116
  } catch {
15055
15117
  continue;
15056
15118
  }
@@ -15141,7 +15203,7 @@ var init_gemini = __esm(() => {
15141
15203
  for (const { filePath, project, mtimeMs } of this.chatFiles(sinceMs)) {
15142
15204
  let session;
15143
15205
  try {
15144
- session = JSON.parse(readFileSync29(filePath, "utf-8"));
15206
+ session = JSON.parse(readFileSync30(filePath, "utf-8"));
15145
15207
  } catch {
15146
15208
  continue;
15147
15209
  }
@@ -15182,7 +15244,7 @@ var init_gemini = __esm(() => {
15182
15244
  for (const { filePath, project } of this.chatFiles(sinceMs)) {
15183
15245
  let content;
15184
15246
  try {
15185
- content = readFileSync29(filePath, "utf-8");
15247
+ content = readFileSync30(filePath, "utf-8");
15186
15248
  } catch {
15187
15249
  continue;
15188
15250
  }
@@ -15425,6 +15487,23 @@ function describeScanOutcome(outcome) {
15425
15487
  function scanOutcomeNeedsAttention(outcome) {
15426
15488
  return outcome.status === "permission-denied" || outcome.status === "error";
15427
15489
  }
15490
+ function describeStoreOutcome(outcome) {
15491
+ if (outcome.status === "orphaned") {
15492
+ return `not read: nothing on this machine was detected as ${outcome.members.join(" or ")}`;
15493
+ }
15494
+ if (outcome.status === "ok")
15495
+ return null;
15496
+ return describeScanOutcome({
15497
+ agentSlug: outcome.storeId,
15498
+ status: outcome.status,
15499
+ sessions: outcome.sessions,
15500
+ path: outcome.path,
15501
+ ...outcome.detail ? { detail: outcome.detail } : {}
15502
+ });
15503
+ }
15504
+ function storeOutcomeNeedsAttention(outcome) {
15505
+ return outcome.status === "orphaned" || outcome.status === "permission-denied" || outcome.status === "error";
15506
+ }
15428
15507
 
15429
15508
  // src/utils/insight-id.ts
15430
15509
  import { createHash as createHash3 } from "node:crypto";
@@ -15437,7 +15516,7 @@ function insightLocalKey(teaches, slug) {
15437
15516
  var init_insight_id = () => {};
15438
15517
 
15439
15518
  // src/reflect/insight-store.ts
15440
- import { existsSync as existsSync41, readFileSync as readFileSync30 } from "fs";
15519
+ import { existsSync as existsSync41, readFileSync as readFileSync31 } from "fs";
15441
15520
  import { join as join35 } from "path";
15442
15521
  import { homedir as homedir17 } from "os";
15443
15522
  function storePath2() {
@@ -15448,7 +15527,7 @@ function readAll() {
15448
15527
  if (!existsSync41(path2))
15449
15528
  return {};
15450
15529
  try {
15451
- const parsed = JSON.parse(readFileSync30(path2, "utf-8"));
15530
+ const parsed = JSON.parse(readFileSync31(path2, "utf-8"));
15452
15531
  return parsed && typeof parsed === "object" ? parsed : {};
15453
15532
  } catch {
15454
15533
  return {};
@@ -15493,7 +15572,7 @@ var init_insight_store = __esm(() => {
15493
15572
  var DEFAULT_DAILY_TIER2_BUDGET = 3;
15494
15573
 
15495
15574
  // src/reflect/cadence.ts
15496
- import { existsSync as existsSync42, readFileSync as readFileSync31 } from "fs";
15575
+ import { existsSync as existsSync42, readFileSync as readFileSync32 } from "fs";
15497
15576
  import { join as join36 } from "path";
15498
15577
  import { homedir as homedir18 } from "os";
15499
15578
  function remainingDailyAnalyses(state, now = new Date, budget = DEFAULT_DAILY_TIER2_BUDGET) {
@@ -15515,7 +15594,7 @@ function loadCadenceState() {
15515
15594
  const p = statePath();
15516
15595
  if (!existsSync42(p))
15517
15596
  return { ...DEFAULT_STATE };
15518
- const parsed = JSON.parse(readFileSync31(p, "utf-8"));
15597
+ const parsed = JSON.parse(readFileSync32(p, "utf-8"));
15519
15598
  const state = { ...DEFAULT_STATE, ...parsed && typeof parsed === "object" ? parsed : {} };
15520
15599
  if (state.enabled === false && state.disabledByUser !== true) {
15521
15600
  state.enabled = true;
@@ -15576,7 +15655,7 @@ __export(exports_run_log, {
15576
15655
  RUN_LOG_CAP: () => RUN_LOG_CAP,
15577
15656
  ANALYST_ERROR_MAX_CHARS: () => ANALYST_ERROR_MAX_CHARS
15578
15657
  });
15579
- import { existsSync as existsSync43, mkdirSync as mkdirSync25, readFileSync as readFileSync32, readdirSync as readdirSync15, statSync as statSync9, unlinkSync as unlinkSync7, writeFileSync as writeFileSync25 } from "fs";
15658
+ import { existsSync as existsSync43, mkdirSync as mkdirSync25, readFileSync as readFileSync33, readdirSync as readdirSync15, statSync as statSync9, unlinkSync as unlinkSync7, writeFileSync as writeFileSync25 } from "fs";
15580
15659
  import { dirname as dirname10, join as join37 } from "path";
15581
15660
  import { homedir as homedir19 } from "os";
15582
15661
  function runLogPath() {
@@ -15587,7 +15666,7 @@ function loadRunLog() {
15587
15666
  const p = runLogPath();
15588
15667
  if (!existsSync43(p))
15589
15668
  return [];
15590
- const parsed = JSON.parse(readFileSync32(p, "utf-8"));
15669
+ const parsed = JSON.parse(readFileSync33(p, "utf-8"));
15591
15670
  return Array.isArray(parsed) ? parsed : [];
15592
15671
  } catch {
15593
15672
  return [];
@@ -15755,7 +15834,7 @@ var init_run_log = __esm(() => {
15755
15834
  });
15756
15835
 
15757
15836
  // src/reflect/conversation-queue.ts
15758
- import { existsSync as existsSync44, readFileSync as readFileSync33 } from "fs";
15837
+ import { existsSync as existsSync44, readFileSync as readFileSync34 } from "fs";
15759
15838
  import { join as join38 } from "path";
15760
15839
  import { homedir as homedir20 } from "os";
15761
15840
  function conversationKey(c) {
@@ -15769,7 +15848,7 @@ function loadQueueState() {
15769
15848
  const p = queuePath();
15770
15849
  if (!existsSync44(p))
15771
15850
  return { entries: {} };
15772
- const parsed = JSON.parse(readFileSync33(p, "utf-8"));
15851
+ const parsed = JSON.parse(readFileSync34(p, "utf-8"));
15773
15852
  if (parsed && typeof parsed === "object" && parsed.entries && typeof parsed.entries === "object") {
15774
15853
  return { entries: parsed.entries };
15775
15854
  }
@@ -15977,7 +16056,7 @@ function parseHandoffResult(kind, text2) {
15977
16056
  }
15978
16057
 
15979
16058
  // src/reflect/model-repair.ts
15980
- import { existsSync as existsSync45, readFileSync as readFileSync34, writeFileSync as writeFileSync26 } from "fs";
16059
+ import { existsSync as existsSync45, readFileSync as readFileSync35, writeFileSync as writeFileSync26 } from "fs";
15981
16060
  import { homedir as homedir21 } from "os";
15982
16061
  import { join as join39 } from "path";
15983
16062
  function codexConfigPath() {
@@ -16014,7 +16093,7 @@ function repairCodexModelPin() {
16014
16093
  const path2 = codexConfigPath();
16015
16094
  if (!existsSync45(path2))
16016
16095
  return null;
16017
- const current = readFileSync34(path2, "utf-8");
16096
+ const current = readFileSync35(path2, "utf-8");
16018
16097
  const stripped = stripModelPin(current);
16019
16098
  if (!stripped)
16020
16099
  return null;
@@ -16837,7 +16916,214 @@ ${all.length} insight(s) from your recent work:
16837
16916
  });
16838
16917
  });
16839
16918
 
16919
+ // src/agents/transcript-stores.ts
16920
+ function joiner(input) {
16921
+ const sep4 = input.sep ?? (input.platform === "win32" ? "\\" : "/");
16922
+ return (...parts) => parts.join(sep4);
16923
+ }
16924
+ function home(input) {
16925
+ return input.homeDir.replace(/[/\\]+$/, "");
16926
+ }
16927
+ function appDataRoot(input) {
16928
+ const join41 = joiner(input);
16929
+ if (input.platform === "darwin")
16930
+ return join41(home(input), "Library", "Application Support");
16931
+ if (input.platform === "win32") {
16932
+ return input.appData ?? join41(home(input), "AppData", "Roaming");
16933
+ }
16934
+ return join41(home(input), ".config");
16935
+ }
16936
+ function localAppDataRoot(input) {
16937
+ const join41 = joiner(input);
16938
+ return input.localAppData ?? join41(home(input), "AppData", "Local");
16939
+ }
16940
+ function codexOriginator(head) {
16941
+ for (const line of head.split(`
16942
+ `)) {
16943
+ if (!line.trim())
16944
+ continue;
16945
+ let o;
16946
+ try {
16947
+ o = JSON.parse(line);
16948
+ } catch {
16949
+ continue;
16950
+ }
16951
+ if (o.type !== "session_meta")
16952
+ continue;
16953
+ const payload = o.payload;
16954
+ return typeof payload?.originator === "string" ? payload.originator : null;
16955
+ }
16956
+ return null;
16957
+ }
16958
+ function claudeEntrypoint(head) {
16959
+ for (const line of head.split(`
16960
+ `)) {
16961
+ if (!line.trim())
16962
+ continue;
16963
+ let o;
16964
+ try {
16965
+ o = JSON.parse(line);
16966
+ } catch {
16967
+ continue;
16968
+ }
16969
+ if (typeof o.entrypoint === "string")
16970
+ return o.entrypoint;
16971
+ }
16972
+ return null;
16973
+ }
16974
+ function attributeCodexOriginator(marker) {
16975
+ switch (marker) {
16976
+ case "Codex Desktop":
16977
+ case "codex_work_desktop":
16978
+ return "codex-app";
16979
+ case "codex-tui":
16980
+ case "codex_exec":
16981
+ case "Claude Code":
16982
+ return "codex";
16983
+ default:
16984
+ return null;
16985
+ }
16986
+ }
16987
+ function attributeClaudeEntrypoint(marker) {
16988
+ switch (marker) {
16989
+ case "cli":
16990
+ case "sdk-cli":
16991
+ return "claude-code";
16992
+ case "claude-desktop":
16993
+ case "local-agent":
16994
+ return "claude-desktop";
16995
+ default:
16996
+ return null;
16997
+ }
16998
+ }
16999
+ function resolveTranscriptStores(input) {
17000
+ const resolved = [];
17001
+ for (const def of TRANSCRIPT_STORES) {
17002
+ const path2 = def.path(input);
17003
+ if (path2 === null)
17004
+ continue;
17005
+ resolved.push({ def, path: path2, altPaths: def.altPaths?.(input) ?? [] });
17006
+ }
17007
+ return resolved;
17008
+ }
17009
+ function familyMembers(family, table = TRANSCRIPT_STORES) {
17010
+ const slugs = new Set;
17011
+ for (const store of table) {
17012
+ if (store.family !== family)
17013
+ continue;
17014
+ for (const member of store.members)
17015
+ slugs.add(member);
17016
+ }
17017
+ return [...slugs];
17018
+ }
17019
+ function isStoreUnlocked(def, detectedSlugs, table = TRANSCRIPT_STORES) {
17020
+ const detected = detectedSlugs instanceof Set ? detectedSlugs : new Set(detectedSlugs);
17021
+ return familyMembers(def.family, table).some((m) => detected.has(m));
17022
+ }
17023
+ function telemetryOwner(def, detectedSlugs) {
17024
+ const detected = detectedSlugs instanceof Set ? detectedSlugs : new Set(detectedSlugs);
17025
+ if (detected.has(def.readerSlug))
17026
+ return def.readerSlug;
17027
+ return def.members.find((m) => detected.has(m)) ?? null;
17028
+ }
17029
+ function suppressedStoreReaders(detectedSlugs, sharesImplementation, table = TRANSCRIPT_STORES) {
17030
+ const detected = detectedSlugs instanceof Set ? detectedSlugs : new Set(detectedSlugs);
17031
+ const suppressed = new Set;
17032
+ for (const store of table) {
17033
+ const owner = telemetryOwner(store, detected);
17034
+ if (owner === null)
17035
+ continue;
17036
+ for (const member of store.members) {
17037
+ if (member === owner || !detected.has(member))
17038
+ continue;
17039
+ if (sharesImplementation(member, owner))
17040
+ suppressed.add(member);
17041
+ }
17042
+ }
17043
+ return suppressed;
17044
+ }
17045
+ function attributeTranscript(def, head) {
17046
+ if (head === null || !def.marker) {
17047
+ return { agentSlug: def.defaultMember, marker: null, recognised: false };
17048
+ }
17049
+ const marker = def.marker(head);
17050
+ if (marker === null)
17051
+ return { agentSlug: def.defaultMember, marker: null, recognised: false };
17052
+ const slug = def.attribute?.(marker) ?? null;
17053
+ return slug === null ? { agentSlug: def.defaultMember, marker, recognised: false } : { agentSlug: slug, marker, recognised: true };
17054
+ }
17055
+ var CODEX_HEAD, CLAUDE_HEAD, TRANSCRIPT_STORES;
17056
+ var init_transcript_stores = __esm(() => {
17057
+ CODEX_HEAD = 256 * 1024;
17058
+ CLAUDE_HEAD = 64 * 1024;
17059
+ TRANSCRIPT_STORES = [
17060
+ {
17061
+ id: "codex/sessions",
17062
+ readerSlug: "codex",
17063
+ family: "codex",
17064
+ members: ["codex", "codex-app"],
17065
+ defaultMember: "codex",
17066
+ kind: "dir",
17067
+ path: (i) => joiner(i)(home(i), ".codex", "sessions"),
17068
+ matches: (n) => n.startsWith("rollout-") && n.endsWith(".jsonl"),
17069
+ headBytes: CODEX_HEAD,
17070
+ marker: codexOriginator,
17071
+ attribute: attributeCodexOriginator
17072
+ },
17073
+ {
17074
+ id: "claude/projects",
17075
+ readerSlug: "claude-code",
17076
+ family: "claude",
17077
+ members: ["claude-code", "claude-desktop"],
17078
+ defaultMember: "claude-code",
17079
+ kind: "dir",
17080
+ path: (i) => joiner(i)(home(i), ".claude", "projects"),
17081
+ matches: (n) => n.endsWith(".jsonl"),
17082
+ subordinate: (rel) => rel.split(/[\\/]/).length > 2,
17083
+ headBytes: CLAUDE_HEAD,
17084
+ marker: claudeEntrypoint,
17085
+ attribute: attributeClaudeEntrypoint
17086
+ },
17087
+ {
17088
+ id: "claude/cowork",
17089
+ readerSlug: "claude-desktop",
17090
+ family: "claude",
17091
+ members: ["claude-desktop"],
17092
+ defaultMember: "claude-desktop",
17093
+ kind: "dir",
17094
+ path: (i) => joiner(i)(appDataRoot(i), "Claude", "local-agent-mode-sessions"),
17095
+ altPaths: (i) => i.platform === "win32" ? [joiner(i)(localAppDataRoot(i), "Packages", "Claude_pzs8sxrjxfjjc", "LocalCache", "Roaming", "Claude", "local-agent-mode-sessions")] : [],
17096
+ matches: (n) => n.endsWith(".jsonl"),
17097
+ headBytes: CLAUDE_HEAD,
17098
+ marker: claudeEntrypoint,
17099
+ attribute: attributeClaudeEntrypoint,
17100
+ note: "macOS TCC can refuse this while it still exists"
17101
+ },
17102
+ {
17103
+ id: "gemini/tmp",
17104
+ readerSlug: "gemini",
17105
+ family: "gemini",
17106
+ members: ["gemini"],
17107
+ defaultMember: "gemini",
17108
+ kind: "dir",
17109
+ path: (i) => joiner(i)(home(i), ".gemini", "tmp"),
17110
+ matches: (n) => n.endsWith(".json")
17111
+ },
17112
+ {
17113
+ id: "cursor/state",
17114
+ readerSlug: "cursor",
17115
+ family: "cursor",
17116
+ members: ["cursor"],
17117
+ defaultMember: "cursor",
17118
+ kind: "file",
17119
+ path: (i) => joiner(i)(appDataRoot(i), "Cursor", "User", "globalStorage", "state.vscdb"),
17120
+ tool: "sqlite"
17121
+ }
17122
+ ];
17123
+ });
17124
+
16840
17125
  // src/reflect/conversation-registry.ts
17126
+ import { homedir as homedir22, platform as platform7 } from "os";
16841
17127
  function computeStatus(lastActivityAt, nowMs, idleMinutes = DEFAULT_IDLE_MINUTES) {
16842
17128
  const lastMs = new Date(lastActivityAt).getTime();
16843
17129
  if (Number.isNaN(lastMs))
@@ -16868,44 +17154,114 @@ function mergeSessionListings(listings, opts) {
16868
17154
  status: isFreshEndStamp(s.endedAt, s.lastActivityAt) ? "finished" : computeStatus(s.lastActivityAt, opts.nowMs, opts.idleMinutes)
16869
17155
  }));
16870
17156
  }
17157
+ function machineStores(opts) {
17158
+ return opts.stores ?? resolveTranscriptStores({
17159
+ platform: platform7(),
17160
+ homeDir: homedir22(),
17161
+ appData: process.env.APPDATA ?? null,
17162
+ localAppData: process.env.LOCALAPPDATA ?? null
17163
+ });
17164
+ }
17165
+ function attributeListing(store, sessions) {
17166
+ if (!store.def.attribute)
17167
+ return sessions;
17168
+ return sessions.map((s) => {
17169
+ const surface = s.surface ?? null;
17170
+ const slug = surface === null ? null : store.def.attribute?.(surface) ?? null;
17171
+ return {
17172
+ ...s,
17173
+ agentSlug: slug ?? store.def.defaultMember,
17174
+ surface
17175
+ };
17176
+ });
17177
+ }
16871
17178
  async function listLocalConversations(opts = {}) {
16872
- const adapters = await detectAgents();
17179
+ const detected = opts.detected ?? (await detectAgents()).map((a) => a.slug);
17180
+ const detectedSet = new Set(detected);
16873
17181
  const sinceISO = opts.sinceISO ?? null;
17182
+ const maxPerStore = opts.maxPerStore ?? DEFAULT_MAX_PER_STORE;
16874
17183
  const listings = [];
16875
- const perAgent = [];
16876
- for (const adapter2 of adapters) {
16877
- if (!adapter2.listSessions) {
16878
- perAgent.push({ agentSlug: adapter2.slug, status: "no-reader", sessions: null });
17184
+ const perStore = [];
17185
+ const stores = machineStores(opts);
17186
+ const table = stores.map((s) => s.def);
17187
+ for (const store of stores) {
17188
+ const base = {
17189
+ storeId: store.def.id,
17190
+ family: store.def.family,
17191
+ members: [...familyMembers(store.def.family, table)],
17192
+ path: store.path
17193
+ };
17194
+ if (!isStoreUnlocked(store.def, detectedSet, table)) {
17195
+ perStore.push({ ...base, status: "orphaned", sessions: null });
17196
+ continue;
17197
+ }
17198
+ const reader = (opts.readerFor ?? getAdapterBySlug)(store.def.readerSlug);
17199
+ if (!reader?.listSessions) {
17200
+ perStore.push({ ...base, status: "no-reader", sessions: null });
16879
17201
  continue;
16880
17202
  }
16881
17203
  try {
16882
- const sessions = await adapter2.listSessions(sinceISO);
17204
+ const sessions = await reader.listSessions(sinceISO);
16883
17205
  if (sessions === null) {
16884
- perAgent.push(diagnoseTranscriptRead(adapter2));
17206
+ const outcome = diagnoseTranscriptRead(reader);
17207
+ perStore.push({ ...base, status: outcome.status, sessions: null, ...outcome.detail ? { detail: outcome.detail } : {} });
16885
17208
  continue;
16886
17209
  }
16887
- listings.push(sessions);
16888
- perAgent.push({ agentSlug: adapter2.slug, status: "ok", sessions: sessions.length });
17210
+ const attributed = attributeListing(store, sessions).sort((a, b) => b.lastActivityAt.localeCompare(a.lastActivityAt)).slice(0, maxPerStore);
17211
+ listings.push(attributed);
17212
+ perStore.push({
17213
+ ...base,
17214
+ status: "ok",
17215
+ sessions: attributed.length,
17216
+ ...sessions.length > attributed.length ? { truncated: sessions.length } : {}
17217
+ });
16889
17218
  } catch (err) {
16890
- perAgent.push(diagnoseTranscriptRead(adapter2, err));
17219
+ const outcome = diagnoseTranscriptRead(reader, err);
17220
+ perStore.push({ ...base, status: outcome.status, sessions: null, ...outcome.detail ? { detail: outcome.detail } : {} });
16891
17221
  }
16892
17222
  }
16893
17223
  const conversations = mergeSessionListings(listings, {
16894
17224
  nowMs: opts.nowMs ?? Date.now(),
16895
17225
  idleMinutes: opts.idleMinutes
16896
17226
  });
16897
- return { conversations, perAgent };
17227
+ return { conversations, perAgent: derivePerAgent(perStore, conversations), perStore };
17228
+ }
17229
+ function derivePerAgent(perStore, conversations) {
17230
+ const counts = new Map;
17231
+ for (const c of conversations)
17232
+ counts.set(c.agentSlug, (counts.get(c.agentSlug) ?? 0) + 1);
17233
+ const rows = new Map;
17234
+ for (const store of perStore) {
17235
+ for (const slug of store.members) {
17236
+ const existing = rows.get(slug);
17237
+ if (store.status === "ok") {
17238
+ rows.set(slug, { agentSlug: slug, status: "ok", sessions: counts.get(slug) ?? 0 });
17239
+ continue;
17240
+ }
17241
+ if (!existing || existing.status !== "ok") {
17242
+ rows.set(slug, {
17243
+ agentSlug: slug,
17244
+ status: store.status === "orphaned" ? "missing-dir" : store.status,
17245
+ sessions: null,
17246
+ ...store.path ? { path: store.path } : {},
17247
+ ...store.detail ? { detail: store.detail } : {}
17248
+ });
17249
+ }
17250
+ }
17251
+ }
17252
+ return [...rows.values()];
16898
17253
  }
16899
- var DEFAULT_IDLE_MINUTES = 10;
17254
+ var DEFAULT_IDLE_MINUTES = 10, DEFAULT_MAX_PER_STORE = 500;
16900
17255
  var init_conversation_registry = __esm(async () => {
16901
17256
  init_transcript_sources();
17257
+ init_transcript_stores();
16902
17258
  await init_detect();
16903
17259
  });
16904
17260
 
16905
17261
  // src/reflect/session-summary.ts
16906
17262
  import { createHash as createHash4 } from "crypto";
16907
17263
  import { execFileSync as execFileSync3 } from "child_process";
16908
- import { readFileSync as readFileSync35 } from "fs";
17264
+ import { readFileSync as readFileSync36 } from "fs";
16909
17265
  import { isAbsolute as isAbsolute4 } from "path";
16910
17266
  function validateAssetMarkers(markers, knownSkills) {
16911
17267
  if (!markers || markers.length === 0)
@@ -17007,7 +17363,7 @@ function digestForEntry(entry) {
17007
17363
  return null;
17008
17364
  let content;
17009
17365
  try {
17010
- content = readFileSync35(entry.transcriptPath, "utf-8");
17366
+ content = readFileSync36(entry.transcriptPath, "utf-8");
17011
17367
  } catch {
17012
17368
  return null;
17013
17369
  }
@@ -17135,18 +17491,18 @@ var init_session_summary = __esm(() => {
17135
17491
  });
17136
17492
 
17137
17493
  // src/reflect/telemetry-outbox.ts
17138
- import { existsSync as existsSync46, readFileSync as readFileSync36 } from "fs";
17139
- import { join as join41 } from "path";
17140
- import { homedir as homedir22 } from "os";
17494
+ import { existsSync as existsSync47, readFileSync as readFileSync37 } from "fs";
17495
+ import { join as join42 } from "path";
17496
+ import { homedir as homedir23 } from "os";
17141
17497
  function outboxPath() {
17142
- return join41(homedir22(), ".runwork", "telemetry-outbox.json");
17498
+ return join42(homedir23(), ".runwork", "telemetry-outbox.json");
17143
17499
  }
17144
17500
  function loadTelemetryOutbox() {
17145
17501
  try {
17146
17502
  const p = outboxPath();
17147
- if (!existsSync46(p))
17503
+ if (!existsSync47(p))
17148
17504
  return [];
17149
- const parsed = JSON.parse(readFileSync36(p, "utf-8"));
17505
+ const parsed = JSON.parse(readFileSync37(p, "utf-8"));
17150
17506
  if (!Array.isArray(parsed))
17151
17507
  return [];
17152
17508
  return parsed.filter((e) => !!e && typeof e === "object" && typeof e.dedupeKey === "string" && !!e.event && typeof e.event === "object");
@@ -17207,8 +17563,8 @@ var init_active_time = __esm(() => {
17207
17563
 
17208
17564
  // src/reflect/pattern-store.ts
17209
17565
  import { createHash as createHash5 } from "crypto";
17210
- import { join as join42 } from "path";
17211
- import { homedir as homedir23 } from "os";
17566
+ import { join as join43 } from "path";
17567
+ import { homedir as homedir24 } from "os";
17212
17568
  function addBuckets(a, b) {
17213
17569
  if (!a)
17214
17570
  return b ? { ...b } : null;
@@ -17369,7 +17725,7 @@ function buildPatternEvent(payload, nowISO) {
17369
17725
  };
17370
17726
  }
17371
17727
  function storePath3() {
17372
- return join42(homedir23(), ".runwork", "pattern-store.json");
17728
+ return join43(homedir24(), ".runwork", "pattern-store.json");
17373
17729
  }
17374
17730
  function loadPatternStore() {
17375
17731
  const parsed = readJsonOrNull(storePath3());
@@ -17579,7 +17935,7 @@ var init_triage = __esm(async () => {
17579
17935
  });
17580
17936
 
17581
17937
  // src/reflect/conversation-analysis.ts
17582
- import { existsSync as existsSync47 } from "fs";
17938
+ import { existsSync as existsSync48 } from "fs";
17583
17939
  import { basename as basename5 } from "path";
17584
17940
  function brokenAnalystBinaries() {
17585
17941
  return TIER2_ANALYSTS.filter((a) => {
@@ -17607,7 +17963,7 @@ function isPromptStillValid(key) {
17607
17963
  if (!standing?.promptPath || standing.promptConversationKey !== key)
17608
17964
  return false;
17609
17965
  try {
17610
- return existsSync47(standing.promptPath);
17966
+ return existsSync48(standing.promptPath);
17611
17967
  } catch {
17612
17968
  return false;
17613
17969
  }
@@ -20661,6 +21017,159 @@ var skillsCommand = new Command13("skills").description("Manage workspace skills
20661
21017
  // src/index.ts
20662
21018
  await init_reflect();
20663
21019
 
21020
+ // src/commands/conversations.ts
21021
+ init_transcript_stores();
21022
+ await init_detect();
21023
+ import { Command as Command15 } from "commander";
21024
+ import { join as join44 } from "path";
21025
+ import { homedir as homedir25, platform as platform8 } from "os";
21026
+
21027
+ // src/agents/store-census.ts
21028
+ init_transcript_stores();
21029
+ import { readdirSync as readdirSync16, statSync as statSync10, existsSync as existsSync46, openSync as openSync5, readSync as readSync3, closeSync as closeSync5 } from "fs";
21030
+ import { join as join41 } from "path";
21031
+ function sanitizeMarker(raw) {
21032
+ const cleaned = raw.replace(/[^\x20-\x7E]/g, "").trim();
21033
+ return cleaned.length > 64 ? `${cleaned.slice(0, 63)}…` : cleaned;
21034
+ }
21035
+ function readHead(path2, n) {
21036
+ let fd;
21037
+ try {
21038
+ fd = openSync5(path2, "r");
21039
+ const buf = Buffer.alloc(n);
21040
+ const read = readSync3(fd, buf, 0, n, 0);
21041
+ return buf.subarray(0, read).toString("utf-8");
21042
+ } catch {
21043
+ return null;
21044
+ } finally {
21045
+ if (fd !== undefined) {
21046
+ try {
21047
+ closeSync5(fd);
21048
+ } catch {}
21049
+ }
21050
+ }
21051
+ }
21052
+ function isPermissionError(err) {
21053
+ const code = err?.code;
21054
+ return code === "EACCES" || code === "EPERM";
21055
+ }
21056
+ function isMissingError(err) {
21057
+ const code = err?.code;
21058
+ return code === "ENOENT" || code === "ENOTDIR";
21059
+ }
21060
+ function collect(dir, def, out, budget) {
21061
+ if (budget.left <= 0)
21062
+ return;
21063
+ const entries = readdirSync16(dir, { withFileTypes: true });
21064
+ for (const e of entries) {
21065
+ if (budget.left <= 0)
21066
+ return;
21067
+ const full = join41(dir, e.name);
21068
+ if (e.isDirectory()) {
21069
+ try {
21070
+ collect(full, def, out, budget);
21071
+ } catch (err) {
21072
+ if (isPermissionError(err))
21073
+ throw err;
21074
+ }
21075
+ } else if (!def.matches || def.matches(e.name)) {
21076
+ out.push(full);
21077
+ budget.left--;
21078
+ }
21079
+ }
21080
+ }
21081
+ var DEFAULT_MAX_FILES = 2000;
21082
+ function censusStore(store, unlocked, opts = {}) {
21083
+ const { def, path: path2, altPaths } = store;
21084
+ const base = {
21085
+ storeId: def.id,
21086
+ family: def.family,
21087
+ members: def.members,
21088
+ path: path2,
21089
+ unlocked,
21090
+ status: "ok"
21091
+ };
21092
+ const altHits = altPaths.filter((p) => {
21093
+ try {
21094
+ return existsSync46(p);
21095
+ } catch {
21096
+ return false;
21097
+ }
21098
+ });
21099
+ if (altHits.length > 0)
21100
+ base.altHits = altHits;
21101
+ if (!existsSync46(path2))
21102
+ return { ...base, status: "missing" };
21103
+ if (def.kind === "file") {
21104
+ try {
21105
+ const s = statSync10(path2);
21106
+ return { ...base, files: 1, bytes: s.size, newestAt: new Date(s.mtimeMs).toISOString() };
21107
+ } catch (err) {
21108
+ return { ...base, status: isPermissionError(err) ? "permission-denied" : "error", detail: String(err) };
21109
+ }
21110
+ }
21111
+ const all = [];
21112
+ const budget = { left: opts.maxFiles ?? DEFAULT_MAX_FILES };
21113
+ try {
21114
+ collect(path2, def, all, budget);
21115
+ } catch (err) {
21116
+ if (isPermissionError(err))
21117
+ return { ...base, status: "permission-denied", detail: "EACCES" };
21118
+ if (isMissingError(err))
21119
+ return { ...base, status: "missing" };
21120
+ return { ...base, status: "error", detail: err instanceof Error ? err.message : String(err) };
21121
+ }
21122
+ const files = [];
21123
+ let nested = 0;
21124
+ for (const f of all) {
21125
+ const rel = f.slice(path2.length).replace(/^[\\/]+/, "");
21126
+ if (def.subordinate?.(rel))
21127
+ nested++;
21128
+ else
21129
+ files.push(f);
21130
+ }
21131
+ let bytes = 0;
21132
+ let newest = 0;
21133
+ for (const f of all) {
21134
+ try {
21135
+ const s = statSync10(f);
21136
+ bytes += s.size;
21137
+ if (s.mtimeMs > newest)
21138
+ newest = s.mtimeMs;
21139
+ } catch {}
21140
+ }
21141
+ const result = {
21142
+ ...base,
21143
+ files: files.length,
21144
+ ...nested > 0 ? { nested } : {},
21145
+ bytes,
21146
+ newestAt: newest > 0 ? new Date(newest).toISOString() : null
21147
+ };
21148
+ if (opts.skipMarkers || !def.marker)
21149
+ return result;
21150
+ const counts = new Map;
21151
+ for (const f of files) {
21152
+ const head = readHead(f, def.headBytes ?? 64 * 1024);
21153
+ const { agentSlug, marker, recognised } = attributeTranscript(def, head);
21154
+ const clean = marker === null ? null : sanitizeMarker(marker);
21155
+ const key = clean ?? "\x00none";
21156
+ const existing = counts.get(key);
21157
+ if (existing)
21158
+ existing.count++;
21159
+ else
21160
+ counts.set(key, { marker: clean, count: 1, agentSlug, recognised });
21161
+ }
21162
+ result.markers = [...counts.values()].sort((a, b) => b.count - a.count);
21163
+ return result;
21164
+ }
21165
+ function censusStores(stores, detectedSlugs, opts = {}) {
21166
+ const detected = new Set(detectedSlugs);
21167
+ return stores.map((store) => censusStore(store, isStoreUnlocked(store.def, detected), opts));
21168
+ }
21169
+ function orphanedStoresWithContent(censuses) {
21170
+ return censuses.filter((c) => !c.unlocked && c.status === "ok" && (c.files ?? 0) > 0);
21171
+ }
21172
+
20664
21173
  // src/commands/conversations.ts
20665
21174
  init_conversation_queue();
20666
21175
  init_session_summary();
@@ -20676,10 +21185,7 @@ await __promiseAll([
20676
21185
  init_conversation_registry(),
20677
21186
  init_conversation_analysis()
20678
21187
  ]);
20679
- import { Command as Command15 } from "commander";
20680
- import { join as join43 } from "path";
20681
- import { homedir as homedir24 } from "os";
20682
- var DEFAULT_LOOKBACK_DAYS = 30;
21188
+ var DEFAULT_LOOKBACK_DAYS = 0;
20683
21189
  function sinceFromDays(days) {
20684
21190
  if (days <= 0)
20685
21191
  return null;
@@ -20743,18 +21249,25 @@ function fit(text2, width) {
20743
21249
  return text2.length > width ? text2.slice(0, width - 1) + "…" : text2;
20744
21250
  }
20745
21251
  var conversationsCommand = new Command15("conversations").description("Local AI conversations across your agents (registry, end detection)");
20746
- conversationsCommand.command("list").description("List local conversations across all detected agents (metadata only)").option("--days <n>", "Look back this many days (0 = no limit)", String(DEFAULT_LOOKBACK_DAYS)).option("--idle-minutes <n>", "Idle threshold that marks a conversation finished", String(DEFAULT_IDLE_MINUTES)).action(async (opts, command) => {
21252
+ conversationsCommand.command("list").description("List local conversations across all detected agents (metadata only)").option("--days <n>", "Narrow to this many days (0 = no window, the default)", String(DEFAULT_LOOKBACK_DAYS)).option("--idle-minutes <n>", "Idle threshold that marks a conversation finished", String(DEFAULT_IDLE_MINUTES)).action(async (opts, command) => {
20747
21253
  const json = command.optsWithGlobals().json === true || !process.stdout.isTTY;
20748
21254
  const days = parseDays(opts.days);
20749
21255
  const idleMinutes = Math.max(1, Number(opts.idleMinutes) || DEFAULT_IDLE_MINUTES);
20750
21256
  const result = await listLocalConversations({ sinceISO: sinceFromDays(days), idleMinutes });
20751
21257
  if (json) {
20752
- jsonOut({ conversations: result.conversations, perAgent: result.perAgent });
21258
+ jsonOut({ conversations: result.conversations, perAgent: result.perAgent, perStore: result.perStore });
20753
21259
  return;
20754
21260
  }
20755
21261
  console.log(bold(days > 0 ? `
20756
21262
  Local conversations, last ${days} day(s)` : `
20757
21263
  Local conversations (all)`));
21264
+ for (const s of result.perStore) {
21265
+ const reason = describeStoreOutcome(s);
21266
+ if (reason === null)
21267
+ continue;
21268
+ const line = ` ${s.storeId}: ${reason}`;
21269
+ console.log(storeOutcomeNeedsAttention(s) ? yellow(line) : dim(line));
21270
+ }
20758
21271
  for (const a of result.perAgent) {
20759
21272
  if (a.status === "no-reader")
20760
21273
  continue;
@@ -20780,17 +21293,26 @@ Local conversations (all)`));
20780
21293
  if (result.conversations.length === 0)
20781
21294
  console.log(dim(" none"));
20782
21295
  });
20783
- conversationsCommand.command("status").description("Why each agent did or did not contribute conversations (no conversation data)").option("--days <n>", "Look back this many days (0 = no limit)", String(DEFAULT_LOOKBACK_DAYS)).action(async (opts, command) => {
21296
+ conversationsCommand.command("status").description("Why each agent did or did not contribute conversations (no conversation data)").option("--days <n>", "Narrow to this many days (0 = no window, the default)", String(DEFAULT_LOOKBACK_DAYS)).action(async (opts, command) => {
20784
21297
  const json = command.optsWithGlobals().json === true || !process.stdout.isTTY;
20785
21298
  const days = parseDays(opts.days);
20786
- const { perAgent } = await listLocalConversations({ sinceISO: sinceFromDays(days) });
21299
+ const { perAgent, perStore } = await listLocalConversations({ sinceISO: sinceFromDays(days) });
20787
21300
  if (json) {
20788
- jsonOut({ perAgent });
21301
+ jsonOut({ perAgent, perStore });
20789
21302
  return;
20790
21303
  }
20791
21304
  console.log(bold(days > 0 ? `
20792
21305
  Conversation sources, last ${days} day(s)` : `
20793
21306
  Conversation sources`));
21307
+ for (const s of perStore) {
21308
+ const reason = describeStoreOutcome(s);
21309
+ if (reason === null) {
21310
+ console.log(` ${cyan(s.storeId)}: ${s.sessions} conversation(s)`);
21311
+ } else {
21312
+ console.log(` ${cyan(s.storeId)}: ${storeOutcomeNeedsAttention(s) ? yellow(reason) : dim(reason)}`);
21313
+ }
21314
+ }
21315
+ console.log("");
20794
21316
  for (const a of perAgent) {
20795
21317
  const reason = describeScanOutcome(a);
20796
21318
  if (reason === null) {
@@ -20800,7 +21322,7 @@ Conversation sources`));
20800
21322
  }
20801
21323
  }
20802
21324
  });
20803
- conversationsCommand.command("scan").description("Detect finished conversations (idle threshold) and queue them for reflection").option("--days <n>", "Look back this many days (0 = no limit)", String(DEFAULT_LOOKBACK_DAYS)).option("--idle-minutes <n>", "Idle threshold that marks a conversation finished", String(DEFAULT_IDLE_MINUTES)).action(async (opts, command) => {
21325
+ conversationsCommand.command("scan").description("Detect finished conversations (idle threshold) and queue them for reflection").option("--days <n>", "Narrow to this many days (0 = no window, the default)", String(DEFAULT_LOOKBACK_DAYS)).option("--idle-minutes <n>", "Idle threshold that marks a conversation finished", String(DEFAULT_IDLE_MINUTES)).action(async (opts, command) => {
20804
21326
  const json = command.optsWithGlobals().json === true || !process.stdout.isTTY;
20805
21327
  const days = parseDays(opts.days);
20806
21328
  const idleMinutes = Math.max(1, Number(opts.idleMinutes) || DEFAULT_IDLE_MINUTES);
@@ -20864,9 +21386,10 @@ conversationsCommand.command("scan").description("Detect finished conversations
20864
21386
  generatedAt: new Date().toISOString(),
20865
21387
  idleMinutes,
20866
21388
  conversations: [...listed, ...rescued].sort((a, b) => b.lastActivityAt.localeCompare(a.lastActivityAt)),
20867
- perAgent: result.perAgent
21389
+ perAgent: result.perAgent,
21390
+ perStore: result.perStore
20868
21391
  };
20869
- writeJsonAtomic(join43(homedir24(), ".runwork", "conversations.json"), snapshot);
21392
+ writeJsonAtomic(join44(homedir25(), ".runwork", "conversations.json"), snapshot);
20870
21393
  if (json) {
20871
21394
  jsonOut({ queued: scan.queued, reopened: scan.reopened, pruned: scan.pruned, pending, finished: finished.length, perAgent: result.perAgent });
20872
21395
  return;
@@ -20889,15 +21412,71 @@ conversationsCommand.command("analyze").description("Analyze queued finished con
20889
21412
  }
20890
21413
  console.log(outcome.reason ? dim(describeAnalysisOutcome(outcome)) : green(describeAnalysisOutcome(outcome)));
20891
21414
  });
21415
+ conversationsCommand.command("stores").description("Every local transcript store: what is in it, who wrote it, and whether anything reads it").option("--max-files <n>", "Cap transcripts inspected per store", String(DEFAULT_MAX_FILES)).option("--no-markers", "Skip provenance reads; counts, sizes and mtimes only").action(async (opts, command) => {
21416
+ const json = command.optsWithGlobals().json === true || !process.stdout.isTTY;
21417
+ const maxFiles = Math.max(1, Number(opts.maxFiles) || DEFAULT_MAX_FILES);
21418
+ const detected = (await detectAgents()).map((a) => a.slug);
21419
+ const stores = resolveTranscriptStores({
21420
+ platform: platform8(),
21421
+ homeDir: homedir25(),
21422
+ appData: process.env.APPDATA ?? null,
21423
+ localAppData: process.env.LOCALAPPDATA ?? null
21424
+ });
21425
+ const censuses = censusStores(stores, detected, {
21426
+ maxFiles,
21427
+ skipMarkers: opts.markers === false
21428
+ });
21429
+ if (json) {
21430
+ jsonOut({ detected, stores: censuses });
21431
+ return;
21432
+ }
21433
+ console.log(bold(`
21434
+ Transcript stores`));
21435
+ console.log(dim(` detected agents: ${detected.length > 0 ? detected.join(", ") : "none"}
21436
+ `));
21437
+ for (const c of censuses) {
21438
+ const owner = c.unlocked ? green("read") : yellow("ORPHANED");
21439
+ console.log(`${bold(c.storeId)} ${owner} ${dim(`family ${c.family}: ${c.members.join(", ")}`)}`);
21440
+ console.log(dim(` ${c.path}`));
21441
+ if (c.status !== "ok") {
21442
+ console.log(` ${yellow(c.status)}${c.detail ? dim(` (${c.detail})`) : ""}`);
21443
+ } else {
21444
+ const mb = ((c.bytes ?? 0) / 1e6).toFixed(1);
21445
+ const newest = c.newestAt ? c.newestAt.slice(0, 16).replace("T", " ") : "-";
21446
+ const nested = c.nested ? `, plus ${c.nested} subagent transcript(s)` : "";
21447
+ console.log(dim(` ${c.files} conversation(s)${nested}, ${mb} MB, newest ${newest}`));
21448
+ for (const m of c.markers ?? []) {
21449
+ if (m.marker === null) {
21450
+ console.log(` ${String(m.count).padStart(5)} ${dim(`(no marker, pre-dates the field) -> ${m.agentSlug}`)}`);
21451
+ continue;
21452
+ }
21453
+ const flag = m.recognised ? dim(`-> ${m.agentSlug}`) : yellow(`-> ${m.agentSlug} (UNRECOGNISED surface)`);
21454
+ console.log(` ${String(m.count).padStart(5)} ${cyan(m.marker)} ${flag}`);
21455
+ }
21456
+ }
21457
+ for (const alt of c.altHits ?? []) {
21458
+ console.log(` ${yellow("also present:")} ${dim(alt)}`);
21459
+ }
21460
+ console.log("");
21461
+ }
21462
+ const orphans = orphanedStoresWithContent(censuses);
21463
+ if (orphans.length > 0) {
21464
+ console.log(yellow(`${orphans.length} store(s) hold transcripts that no detected agent reads:`));
21465
+ for (const o of orphans) {
21466
+ console.log(` ${o.path} ${dim(`(${o.files} transcripts; needs one of: ${o.members.join(", ")})`)}`);
21467
+ }
21468
+ console.log("");
21469
+ }
21470
+ });
20892
21471
 
20893
21472
  // src/commands/instructions.ts
20894
21473
  init_store();
20895
21474
  init_client();
20896
21475
  init_resolve();
20897
21476
  import { Command as Command16 } from "commander";
20898
- import { readFileSync as readFileSync37, existsSync as existsSync48 } from "fs";
20899
- import { join as join44 } from "path";
20900
- import { homedir as homedir25 } from "os";
21477
+ import { readFileSync as readFileSync38, existsSync as existsSync49 } from "fs";
21478
+ import { join as join45 } from "path";
21479
+ import { homedir as homedir26 } from "os";
20901
21480
 
20902
21481
  // ../../shared/agent-instructions/runwork-instructions.ts
20903
21482
  function formatList(items, max = 8) {
@@ -21377,13 +21956,13 @@ async function buildInstructionContext(client, workspace) {
21377
21956
  // src/commands/instructions.ts
21378
21957
  function readSetupExtras(workspaceId) {
21379
21958
  for (const path2 of [
21380
- join44(process.cwd(), ".runwork", "setup.json"),
21381
- join44(homedir25(), ".runwork", "setup.json")
21959
+ join45(process.cwd(), ".runwork", "setup.json"),
21960
+ join45(homedir26(), ".runwork", "setup.json")
21382
21961
  ]) {
21383
- if (!existsSync48(path2))
21962
+ if (!existsSync49(path2))
21384
21963
  continue;
21385
21964
  try {
21386
- const state = JSON.parse(readFileSync37(path2, "utf-8"));
21965
+ const state = JSON.parse(readFileSync38(path2, "utf-8"));
21387
21966
  if (state.workspaceId === workspaceId) {
21388
21967
  return { workspaceSlug: state.workspaceSlug, persona: state.persona };
21389
21968
  }
@@ -21427,16 +22006,16 @@ import { Command as Command17 } from "commander";
21427
22006
  import * as path3 from "node:path";
21428
22007
 
21429
22008
  // src/utils/data-input.ts
21430
- import { readFileSync as readFileSync38, existsSync as existsSync49 } from "fs";
22009
+ import { readFileSync as readFileSync39, existsSync as existsSync50 } from "fs";
21431
22010
  async function parseDataInput(dataFlag) {
21432
22011
  if (dataFlag) {
21433
22012
  if (dataFlag.startsWith("@")) {
21434
22013
  const filePath = dataFlag.slice(1);
21435
- if (!existsSync49(filePath)) {
22014
+ if (!existsSync50(filePath)) {
21436
22015
  console.error(`File not found: ${filePath}`);
21437
22016
  process.exit(1);
21438
22017
  }
21439
- const content = readFileSync38(filePath, "utf-8");
22018
+ const content = readFileSync39(filePath, "utf-8");
21440
22019
  return parseJson(content, filePath);
21441
22020
  }
21442
22021
  return parseJson(dataFlag, "--data");
@@ -22490,7 +23069,7 @@ init_resolve();
22490
23069
  init_prompt();
22491
23070
  init_http();
22492
23071
  import { Command as Command21 } from "commander";
22493
- import { writeFileSync as writeFileSync29, readFileSync as readFileSync39 } from "fs";
23072
+ import { writeFileSync as writeFileSync29, readFileSync as readFileSync40 } from "fs";
22494
23073
  import { basename as basename6 } from "path";
22495
23074
  function formatSize(bytes) {
22496
23075
  if (bytes === undefined)
@@ -22600,7 +23179,7 @@ var uploadCommand = new Command21("upload").description("Upload a local file to
22600
23179
  const { workspaceId } = await resolveWorkspace2(client, opts);
22601
23180
  const objectKey = key || basename6(localPath);
22602
23181
  try {
22603
- const fileBuffer = readFileSync39(localPath);
23182
+ const fileBuffer = readFileSync40(localPath);
22604
23183
  const { url } = await client.getPresignedUrl(workspaceId, bucket, { action: "write", key: objectKey });
22605
23184
  const response = await httpFetch(url, { method: "PUT", body: fileBuffer });
22606
23185
  if (!response.ok) {
@@ -23117,8 +23696,8 @@ init_resolve();
23117
23696
  init_prompt();
23118
23697
  await init_detect();
23119
23698
  import { Command as Command27 } from "commander";
23120
- import { join as join49 } from "path";
23121
- import { homedir as homedir28 } from "os";
23699
+ import { join as join50 } from "path";
23700
+ import { homedir as homedir29 } from "os";
23122
23701
 
23123
23702
  // src/commands/sync.ts
23124
23703
  init_store();
@@ -23129,9 +23708,9 @@ await __promiseAll([
23129
23708
  init_codex()
23130
23709
  ]);
23131
23710
  import { Command as Command26 } from "commander";
23132
- import { readFileSync as readFileSync41, existsSync as existsSync52 } from "fs";
23133
- import { join as join48 } from "path";
23134
- import { homedir as homedir27 } from "os";
23711
+ import { readFileSync as readFileSync42, existsSync as existsSync53 } from "fs";
23712
+ import { join as join49 } from "path";
23713
+ import { homedir as homedir28 } from "os";
23135
23714
 
23136
23715
  // src/commands/mcp-entries.ts
23137
23716
  init_types();
@@ -23195,6 +23774,7 @@ var RUNWORK_AGENT_DEFAULTS = {
23195
23774
  };
23196
23775
  var AGENT_DEFAULTS_SCHEMA_VERSION = 1;
23197
23776
  // src/commands/sync-telemetry.ts
23777
+ init_transcript_stores();
23198
23778
  var TELEMETRY_BACKFILL_MS = 30 * 24 * 60 * 60 * 1000;
23199
23779
  function resolveTelemetrySince(state, nowMs = Date.now()) {
23200
23780
  if (state.lastTelemetryAt)
@@ -23205,11 +23785,20 @@ async function collectTelemetryEvents(params) {
23205
23785
  const now = params.now ?? new Date().toISOString();
23206
23786
  const events = [];
23207
23787
  const adapterResults = [];
23788
+ const bySlug = new Map(params.adapters.map((a) => [a.slug, a]));
23789
+ const suppressed = suppressedStoreReaders(params.adapters.map((a) => a.slug), (a, b) => {
23790
+ const left = bySlug.get(a);
23791
+ const right = bySlug.get(b);
23792
+ if (!left || !right)
23793
+ return false;
23794
+ return left.readUsageStats !== undefined && left.readUsageStats === right.readUsageStats || left.readSkillUsage !== undefined && left.readSkillUsage === right.readSkillUsage;
23795
+ });
23208
23796
  for (const adapter2 of params.adapters) {
23209
23797
  let stats = "unsupported";
23210
23798
  let skills = "unsupported";
23211
23799
  let error;
23212
- if (adapter2.readUsageStats) {
23800
+ const readsStore = !suppressed.has(adapter2.slug);
23801
+ if (adapter2.readUsageStats && readsStore) {
23213
23802
  try {
23214
23803
  stats = await adapter2.readUsageStats(params.since);
23215
23804
  if (stats && stats.hasNewActivity) {
@@ -23237,7 +23826,7 @@ async function collectTelemetryEvents(params) {
23237
23826
  stats = null;
23238
23827
  }
23239
23828
  }
23240
- if (adapter2.readSkillUsage) {
23829
+ if (adapter2.readSkillUsage && readsStore) {
23241
23830
  try {
23242
23831
  skills = await adapter2.readSkillUsage(params.since);
23243
23832
  if (skills && skills.length > 0) {
@@ -24013,10 +24602,10 @@ function sameStringSet(a, b) {
24013
24602
  }
24014
24603
 
24015
24604
  // src/utils/sync-lock.ts
24016
- import { existsSync as existsSync51, mkdirSync as mkdirSync28, readFileSync as readFileSync40, unlinkSync as unlinkSync8, writeFileSync as writeFileSync30 } from "fs";
24017
- import { join as join47 } from "path";
24018
- import { homedir as homedir26 } from "os";
24019
- var LOCK_PATH = join47(homedir26(), ".runwork", "sync.lock");
24605
+ import { existsSync as existsSync52, mkdirSync as mkdirSync28, readFileSync as readFileSync41, unlinkSync as unlinkSync8, writeFileSync as writeFileSync30 } from "fs";
24606
+ import { join as join48 } from "path";
24607
+ import { homedir as homedir27 } from "os";
24608
+ var LOCK_PATH = join48(homedir27(), ".runwork", "sync.lock");
24020
24609
  var STALE_LOCK_MS = 5 * 60 * 1000;
24021
24610
  var DEFAULT_WAIT_MS = 30000;
24022
24611
  var exitHandlerRegistered = false;
@@ -24036,15 +24625,15 @@ function isProcessAlive(pid) {
24036
24625
  }
24037
24626
  function readLock() {
24038
24627
  try {
24039
- return JSON.parse(readFileSync40(LOCK_PATH, "utf-8"));
24628
+ return JSON.parse(readFileSync41(LOCK_PATH, "utf-8"));
24040
24629
  } catch {
24041
24630
  return null;
24042
24631
  }
24043
24632
  }
24044
24633
  function writeLockExclusive() {
24045
24634
  try {
24046
- if (!existsSync51(join47(homedir26(), ".runwork"))) {
24047
- mkdirSync28(join47(homedir26(), ".runwork"), { recursive: true });
24635
+ if (!existsSync52(join48(homedir27(), ".runwork"))) {
24636
+ mkdirSync28(join48(homedir27(), ".runwork"), { recursive: true });
24048
24637
  }
24049
24638
  writeFileSync30(LOCK_PATH, JSON.stringify({ pid: process.pid, startedAt: Date.now() }), {
24050
24639
  flag: "wx"
@@ -24113,10 +24702,10 @@ Tip: ${hint.title}`);
24113
24702
  } catch {}
24114
24703
  }
24115
24704
  function loadSetupState(filePath) {
24116
- if (!existsSync52(filePath))
24705
+ if (!existsSync53(filePath))
24117
24706
  return null;
24118
24707
  try {
24119
- return JSON.parse(readFileSync41(filePath, "utf-8"));
24708
+ return JSON.parse(readFileSync42(filePath, "utf-8"));
24120
24709
  } catch {
24121
24710
  return null;
24122
24711
  }
@@ -24137,15 +24726,15 @@ function readLocalSkills(state) {
24137
24726
  if (!baseDir)
24138
24727
  continue;
24139
24728
  for (const skillName of state.skills) {
24140
- const skillMdPath = join48(baseDir, skillName, "SKILL.md");
24141
- if (existsSync52(skillMdPath)) {
24142
- results.push({ name: skillName, content: readFileSync41(skillMdPath, "utf-8") });
24729
+ const skillMdPath = join49(baseDir, skillName, "SKILL.md");
24730
+ if (existsSync53(skillMdPath)) {
24731
+ results.push({ name: skillName, content: readFileSync42(skillMdPath, "utf-8") });
24143
24732
  continue;
24144
24733
  }
24145
24734
  const filename = skillName.toLowerCase().replace(/[^a-z0-9]+/g, "-");
24146
- const flatPath = join48(baseDir, `${filename}.md`);
24147
- if (existsSync52(flatPath)) {
24148
- results.push({ name: skillName, content: readFileSync41(flatPath, "utf-8") });
24735
+ const flatPath = join49(baseDir, `${filename}.md`);
24736
+ if (existsSync53(flatPath)) {
24737
+ results.push({ name: skillName, content: readFileSync42(flatPath, "utf-8") });
24149
24738
  }
24150
24739
  }
24151
24740
  if (results.length > 0)
@@ -24399,9 +24988,9 @@ This account is not a member of "${state.workspaceName || state.workspaceId}".`)
24399
24988
  persona: state.persona
24400
24989
  });
24401
24990
  let projectAppSkillFilter = null;
24402
- if (existsSync52(".runwork.json")) {
24991
+ if (existsSync53(".runwork.json")) {
24403
24992
  try {
24404
- const config = JSON.parse(readFileSync41(".runwork.json", "utf-8"));
24993
+ const config = JSON.parse(readFileSync42(".runwork.json", "utf-8"));
24405
24994
  if (config.appName) {
24406
24995
  projectAppSkillFilter = config.appName.toLowerCase().replace(/[^a-z0-9]+/g, "-");
24407
24996
  }
@@ -24670,7 +25259,7 @@ This account is not a member of "${state.workspaceName || state.workspaceId}".`)
24670
25259
  }
24671
25260
  for (const adapter2 of adapters) {
24672
25261
  if (adapter2 instanceof CodexAdapter) {
24673
- const runworkDir = join48(homedir27(), ".runwork");
25262
+ const runworkDir = join49(homedir28(), ".runwork");
24674
25263
  const result = adapter2.registerDesktopWorkspace(runworkDir, "Runwork");
24675
25264
  if (result === "written") {
24676
25265
  vlog(` [${adapter2.name}] Registered workspace in Codex desktop app`);
@@ -24830,8 +25419,8 @@ var syncCommand = new Command26("sync").description("Sync skills bidirectionally
24830
25419
  verbose: !!opts.verbose,
24831
25420
  redetect: !!opts.redetect
24832
25421
  };
24833
- const projectStatePath = join48(process.cwd(), ".runwork", "setup.json");
24834
- const userStatePath = join48(homedir27(), ".runwork", "setup.json");
25422
+ const projectStatePath = join49(process.cwd(), ".runwork", "setup.json");
25423
+ const userStatePath = join49(homedir28(), ".runwork", "setup.json");
24835
25424
  const projectState = loadSetupState(projectStatePath);
24836
25425
  const userState = loadSetupState(userStatePath);
24837
25426
  if (!projectState && !userState) {
@@ -24900,7 +25489,7 @@ function toSkillFilename(name) {
24900
25489
  return name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
24901
25490
  }
24902
25491
  function loadSetupStateForScope(scope) {
24903
- const path4 = scope === "project" ? join49(process.cwd(), ".runwork", "setup.json") : join49(homedir28(), ".runwork", "setup.json");
25492
+ const path4 = scope === "project" ? join50(process.cwd(), ".runwork", "setup.json") : join50(homedir29(), ".runwork", "setup.json");
24904
25493
  return readJsonOrNull(path4);
24905
25494
  }
24906
25495
  async function parkAndTeardownWorkspace(previous, scopes) {
@@ -25069,8 +25658,8 @@ Re-run without --dry-run to sync workspace data.`);
25069
25658
  }
25070
25659
  persistDefaultWorkspace(workspaceId, workspaceName);
25071
25660
  for (const s of scopes) {
25072
- const dir = s === "project" ? ".runwork" : join49(homedir28(), ".runwork");
25073
- writeJsonAtomic(join49(dir, "setup.json"), state);
25661
+ const dir = s === "project" ? ".runwork" : join50(homedir29(), ".runwork");
25662
+ writeJsonAtomic(join50(dir, "setup.json"), state);
25074
25663
  }
25075
25664
  if (restored)
25076
25665
  clearParkedState(workspaceId);
@@ -25078,7 +25667,7 @@ Re-run without --dry-run to sync workspace data.`);
25078
25667
  Syncing workspace data...
25079
25668
  `);
25080
25669
  for (const s of scopes) {
25081
- const statePath2 = s === "project" ? join49(process.cwd(), ".runwork", "setup.json") : join49(homedir28(), ".runwork", "setup.json");
25670
+ const statePath2 = s === "project" ? join50(process.cwd(), ".runwork", "setup.json") : join50(homedir29(), ".runwork", "setup.json");
25082
25671
  await syncFromState(state, statePath2, credentials, {
25083
25672
  dryRun: false,
25084
25673
  pullOnly: true,
@@ -25098,16 +25687,16 @@ init_client();
25098
25687
  import { Command as Command28 } from "commander";
25099
25688
 
25100
25689
  // src/utils/setup-state.ts
25101
- import { existsSync as existsSync53, readFileSync as readFileSync42 } from "fs";
25102
- import { join as join50 } from "path";
25103
- import { homedir as homedir29 } from "os";
25690
+ import { existsSync as existsSync54, readFileSync as readFileSync43 } from "fs";
25691
+ import { join as join51 } from "path";
25692
+ import { homedir as homedir30 } from "os";
25104
25693
  function loadSetupState2() {
25105
- const projectPath = join50(process.cwd(), ".runwork", "setup.json");
25106
- const userPath = join50(homedir29(), ".runwork", "setup.json");
25694
+ const projectPath = join51(process.cwd(), ".runwork", "setup.json");
25695
+ const userPath = join51(homedir30(), ".runwork", "setup.json");
25107
25696
  for (const p of [projectPath, userPath]) {
25108
- if (existsSync53(p)) {
25697
+ if (existsSync54(p)) {
25109
25698
  try {
25110
- return JSON.parse(readFileSync42(p, "utf-8"));
25699
+ return JSON.parse(readFileSync43(p, "utf-8"));
25111
25700
  } catch {
25112
25701
  continue;
25113
25702
  }
@@ -25166,14 +25755,14 @@ init_client();
25166
25755
  init_types();
25167
25756
  await init_detect();
25168
25757
  import { Command as Command29 } from "commander";
25169
- import { existsSync as existsSync54, readFileSync as readFileSync43 } from "fs";
25170
- import { resolve as resolve3, join as join51 } from "path";
25171
- import { homedir as homedir30 } from "os";
25758
+ import { existsSync as existsSync55, readFileSync as readFileSync44 } from "fs";
25759
+ import { resolve as resolve3, join as join52 } from "path";
25760
+ import { homedir as homedir31 } from "os";
25172
25761
  function loadSetupState3(filePath) {
25173
- if (!existsSync54(filePath))
25762
+ if (!existsSync55(filePath))
25174
25763
  return null;
25175
25764
  try {
25176
- return JSON.parse(readFileSync43(filePath, "utf-8"));
25765
+ return JSON.parse(readFileSync44(filePath, "utf-8"));
25177
25766
  } catch {
25178
25767
  return null;
25179
25768
  }
@@ -25189,8 +25778,8 @@ var buildPluginCommand = new Command29("build-plugin").description("Build an ins
25189
25778
  process.exit(1);
25190
25779
  }
25191
25780
  const credentials = requireAuth();
25192
- const projectStatePath = join51(process.cwd(), ".runwork", "setup.json");
25193
- const userStatePath = join51(homedir30(), ".runwork", "setup.json");
25781
+ const projectStatePath = join52(process.cwd(), ".runwork", "setup.json");
25782
+ const userStatePath = join52(homedir31(), ".runwork", "setup.json");
25194
25783
  const state = loadSetupState3(projectStatePath) ?? loadSetupState3(userStatePath);
25195
25784
  if (!state) {
25196
25785
  console.error("No setup state found. Run `runwork setup` first.");
@@ -25283,14 +25872,14 @@ init_prompt();
25283
25872
  init_subprocess();
25284
25873
  await init_detect();
25285
25874
  import { Command as Command30 } from "commander";
25286
- import { existsSync as existsSync55, readFileSync as readFileSync44, writeFileSync as writeFileSync32, readdirSync as readdirSync16, rmSync as rmSync12, unlinkSync as unlinkSync9, lstatSync, readlinkSync } from "fs";
25287
- import { join as join52, resolve as resolve4, relative as relative5, isAbsolute as isAbsolute5 } from "path";
25288
- import { homedir as homedir31 } from "os";
25875
+ import { existsSync as existsSync56, readFileSync as readFileSync45, writeFileSync as writeFileSync32, readdirSync as readdirSync17, rmSync as rmSync12, unlinkSync as unlinkSync9, lstatSync, readlinkSync } from "fs";
25876
+ import { join as join53, resolve as resolve4, relative as relative5, isAbsolute as isAbsolute5 } from "path";
25877
+ import { homedir as homedir32 } from "os";
25289
25878
  function loadSetupState4(filePath) {
25290
- if (!existsSync55(filePath))
25879
+ if (!existsSync56(filePath))
25291
25880
  return null;
25292
25881
  try {
25293
- return JSON.parse(readFileSync44(filePath, "utf-8"));
25882
+ return JSON.parse(readFileSync45(filePath, "utf-8"));
25294
25883
  } catch {
25295
25884
  return null;
25296
25885
  }
@@ -25298,22 +25887,22 @@ function loadSetupState4(filePath) {
25298
25887
  var PRESERVED_ENTRIES = ["bin", "apps", "trash"];
25299
25888
  function removeRunworkState(stateDir, opts) {
25300
25889
  const result = { removed: [], preserved: [], errors: [] };
25301
- if (!existsSync55(stateDir))
25890
+ if (!existsSync56(stateDir))
25302
25891
  return result;
25303
25892
  const preserve = new Set(PRESERVED_ENTRIES);
25304
25893
  if (opts.keepAuth)
25305
25894
  preserve.add(".credentials");
25306
25895
  let entries;
25307
25896
  try {
25308
- entries = readdirSync16(stateDir);
25897
+ entries = readdirSync17(stateDir);
25309
25898
  } catch (err) {
25310
25899
  result.errors.push(`${stateDir}: ${err instanceof Error ? err.message : err}`);
25311
25900
  return result;
25312
25901
  }
25313
25902
  for (const entry of entries) {
25314
- const target = join52(stateDir, entry);
25903
+ const target = join53(stateDir, entry);
25315
25904
  if (preserve.has(entry)) {
25316
- if (existsSync55(target))
25905
+ if (existsSync56(target))
25317
25906
  result.preserved.push(target);
25318
25907
  continue;
25319
25908
  }
@@ -25329,11 +25918,11 @@ function removeRunworkState(stateDir, opts) {
25329
25918
  var SHELL_PROFILES = [".zshrc", ".zprofile", ".bashrc", ".bash_profile", ".profile"];
25330
25919
  var BIN_DIR_PATTERN = /\.runwork[\\/]bin/;
25331
25920
  function stripRunworkPathLines(file) {
25332
- if (!existsSync55(file))
25921
+ if (!existsSync56(file))
25333
25922
  return false;
25334
25923
  let content;
25335
25924
  try {
25336
- content = readFileSync44(file, "utf-8");
25925
+ content = readFileSync45(file, "utf-8");
25337
25926
  } catch {
25338
25927
  return false;
25339
25928
  }
@@ -25362,7 +25951,7 @@ function stripRunworkPathLines(file) {
25362
25951
  }
25363
25952
  }
25364
25953
  function cleanShellProfilePathEntries() {
25365
- return SHELL_PROFILES.map((name) => join52(homedir31(), name)).filter(stripRunworkPathLines);
25954
+ return SHELL_PROFILES.map((name) => join53(homedir32(), name)).filter(stripRunworkPathLines);
25366
25955
  }
25367
25956
  function cleanPowerShellProfilePathEntries() {
25368
25957
  if (process.platform !== "win32")
@@ -25402,7 +25991,7 @@ function removeRunworkSymlink(linkPath) {
25402
25991
  } catch {
25403
25992
  return false;
25404
25993
  }
25405
- const ours = resolve4(join52(homedir31(), ".runwork", "bin"));
25994
+ const ours = resolve4(join53(homedir32(), ".runwork", "bin"));
25406
25995
  const rel = relative5(ours, resolve4(target));
25407
25996
  const insideOurs = rel === "" || !rel.startsWith("..") && !isAbsolute5(rel);
25408
25997
  if (!insideOurs)
@@ -25415,8 +26004,8 @@ function removeRunworkSymlink(linkPath) {
25415
26004
  }
25416
26005
  }
25417
26006
  var uninstallCommand = new Command30("uninstall").description("Remove all Runwork configuration from local agents (MCP servers, skills, instructions)").option("-y, --yes", "Skip confirmation prompt").option("--keep-auth", "Keep authentication credentials (only remove agent configs)").action(async (opts) => {
25418
- const projectStatePath = join52(process.cwd(), ".runwork", "setup.json");
25419
- const userStatePath = join52(homedir31(), ".runwork", "setup.json");
26007
+ const projectStatePath = join53(process.cwd(), ".runwork", "setup.json");
26008
+ const userStatePath = join53(homedir32(), ".runwork", "setup.json");
25420
26009
  const projectState = loadSetupState4(projectStatePath);
25421
26010
  const userState = loadSetupState4(userStatePath);
25422
26011
  if (!projectState && !userState) {
@@ -25503,8 +26092,8 @@ This will remove all Runwork configuration from your local agents:
25503
26092
  }
25504
26093
  }
25505
26094
  }
25506
- const stateDir = label === "project" ? join52(process.cwd(), ".runwork") : join52(homedir31(), ".runwork");
25507
- if (existsSync55(stateDir)) {
26095
+ const stateDir = label === "project" ? join53(process.cwd(), ".runwork") : join53(homedir32(), ".runwork");
26096
+ if (existsSync56(stateDir)) {
25508
26097
  const outcome = removeRunworkState(stateDir, {
25509
26098
  keepAuth: Boolean(opts.keepAuth) && label === "user"
25510
26099
  });
@@ -25534,7 +26123,7 @@ This will remove all Runwork configuration from your local agents:
25534
26123
  console.log(` - ${file}`);
25535
26124
  }
25536
26125
  const removedLinks = [
25537
- join52(homedir31(), ".local", "bin", "runwork"),
26126
+ join53(homedir32(), ".local", "bin", "runwork"),
25538
26127
  "/usr/local/bin/runwork"
25539
26128
  ].filter(removeRunworkSymlink);
25540
26129
  if (removedLinks.length > 0) {
@@ -25546,7 +26135,7 @@ This will remove all Runwork configuration from your local agents:
25546
26135
  if (process.platform === "win32") {
25547
26136
  console.log("");
25548
26137
  console.log(" Still on your PATH (remove by hand if you want it gone):");
25549
- console.log(` ${join52(homedir31(), ".runwork", "bin")} in your user PATH`);
26138
+ console.log(` ${join53(homedir32(), ".runwork", "bin")} in your user PATH`);
25550
26139
  }
25551
26140
  console.log("");
25552
26141
  if (errors > 0) {
@@ -25672,7 +26261,7 @@ var membersCommand = new Command32("members").description("List workspace member
25672
26261
  init_store();
25673
26262
  init_client();
25674
26263
  import { Command as Command33 } from "commander";
25675
- import { readFileSync as readFileSync45 } from "fs";
26264
+ import { readFileSync as readFileSync46 } from "fs";
25676
26265
  function normalizeApiPath(rawPath, baseUrl) {
25677
26266
  if (/^https?:\/\//i.test(rawPath)) {
25678
26267
  const target = new URL(rawPath);
@@ -25705,7 +26294,7 @@ to be read or pasted manually. Prefer a dedicated command when one exists
25705
26294
  let curlStr = opts.curl;
25706
26295
  if (opts.curlFile) {
25707
26296
  try {
25708
- curlStr = readFileSync45(opts.curlFile, "utf-8");
26297
+ curlStr = readFileSync46(opts.curlFile, "utf-8");
25709
26298
  } catch (err) {
25710
26299
  console.error(`Could not read --curl-file: ${err instanceof Error ? err.message : err}`);
25711
26300
  process.exit(1);
@@ -25725,7 +26314,7 @@ to be read or pasted manually. Prefer a dedicated command when one exists
25725
26314
  let raw = opts.body;
25726
26315
  if (raw.startsWith("@")) {
25727
26316
  try {
25728
- raw = readFileSync45(raw.slice(1), "utf-8");
26317
+ raw = readFileSync46(raw.slice(1), "utf-8");
25729
26318
  } catch (err) {
25730
26319
  console.error(`Could not read body file: ${err instanceof Error ? err.message : err}`);
25731
26320
  process.exit(1);
@@ -25779,9 +26368,9 @@ init_preflight();
25779
26368
  init_credentials();
25780
26369
  await init_detect();
25781
26370
  import { parse as parse2 } from "smol-toml";
25782
- import { existsSync as existsSync56, readFileSync as readFileSync46 } from "fs";
25783
- import { join as join53, sep as sep4 } from "path";
25784
- import { homedir as homedir32, platform as osPlatform2, arch as osArch } from "os";
26371
+ import { existsSync as existsSync57, readFileSync as readFileSync47 } from "fs";
26372
+ import { join as join54, sep as sep4 } from "path";
26373
+ import { homedir as homedir33, platform as osPlatform2, arch as osArch } from "os";
25785
26374
  var BASE_URL2 = process.env.RUNWORK_DOWNLOAD_BASE_URL || "https://runwork.ai";
25786
26375
  var LATEST_JSON_URL2 = `${BASE_URL2}/cli/latest.json`;
25787
26376
  function detectPlatform() {
@@ -25809,10 +26398,10 @@ function buildContext() {
25809
26398
  const credentials = getCredentials();
25810
26399
  const client = credentials ? new ApiClient(credentials) : null;
25811
26400
  let config = null;
25812
- const configPath = join53(process.cwd(), ".runwork.json");
25813
- if (existsSync56(configPath)) {
26401
+ const configPath = join54(process.cwd(), ".runwork.json");
26402
+ if (existsSync57(configPath)) {
25814
26403
  try {
25815
- config = JSON.parse(readFileSync46(configPath, "utf-8"));
26404
+ config = JSON.parse(readFileSync47(configPath, "utf-8"));
25816
26405
  } catch {}
25817
26406
  }
25818
26407
  return { credentials, client, config, cwd: process.cwd() };
@@ -25866,8 +26455,8 @@ async function checkCliVersion() {
25866
26455
  };
25867
26456
  }
25868
26457
  async function checkCliArtifactReachable() {
25869
- const platform7 = detectPlatform();
25870
- if (!platform7.key) {
26458
+ const platform9 = detectPlatform();
26459
+ if (!platform9.key) {
25871
26460
  return {
25872
26461
  name: "cli-artifact",
25873
26462
  status: "skip",
@@ -25883,12 +26472,12 @@ async function checkCliArtifactReachable() {
25883
26472
  fix: "check network / outbound access to runwork.ai"
25884
26473
  };
25885
26474
  }
25886
- const entry = manifest.artifacts?.[platform7.key];
26475
+ const entry = manifest.artifacts?.[platform9.key];
25887
26476
  if (!entry?.path) {
25888
26477
  return {
25889
26478
  name: "cli-artifact",
25890
26479
  status: "fail",
25891
- message: `manifest has no artifact for ${platform7.key}`
26480
+ message: `manifest has no artifact for ${platform9.key}`
25892
26481
  };
25893
26482
  }
25894
26483
  const artifactUrl = `${BASE_URL2}${entry.path}`;
@@ -25901,7 +26490,7 @@ async function checkCliArtifactReachable() {
25901
26490
  message: `${artifactUrl} returned HTTP ${response.status}`
25902
26491
  };
25903
26492
  }
25904
- return { name: "cli-artifact", status: "pass", message: `${platform7.key} reachable` };
26493
+ return { name: "cli-artifact", status: "pass", message: `${platform9.key} reachable` };
25905
26494
  } catch (err) {
25906
26495
  const msg = err instanceof Error ? err.message : String(err);
25907
26496
  return {
@@ -25913,9 +26502,9 @@ async function checkCliArtifactReachable() {
25913
26502
  }
25914
26503
  async function checkCliInstallLocation() {
25915
26504
  const isWindows2 = osPlatform2() === "win32";
25916
- const home = homedir32();
25917
- const canonicalDir = join53(home, ".runwork", "bin");
25918
- const canonicalBinary = isWindows2 ? join53(canonicalDir, "runwork.exe") : join53(canonicalDir, "runwork");
26505
+ const home2 = homedir33();
26506
+ const canonicalDir = join54(home2, ".runwork", "bin");
26507
+ const canonicalBinary = isWindows2 ? join54(canonicalDir, "runwork.exe") : join54(canonicalDir, "runwork");
25919
26508
  const candidates = [process.execPath, process.argv[1] || ""].filter(Boolean);
25920
26509
  const runsFromCanonical = candidates.some((p) => normalizePath(p) === normalizePath(canonicalBinary));
25921
26510
  if (runsFromCanonical) {
@@ -25925,7 +26514,7 @@ async function checkCliInstallLocation() {
25925
26514
  message: `canonical (${canonicalBinary})`
25926
26515
  };
25927
26516
  }
25928
- if (existsSync56(canonicalBinary)) {
26517
+ if (existsSync57(canonicalBinary)) {
25929
26518
  return {
25930
26519
  name: "cli-install-location",
25931
26520
  status: "warn",
@@ -26058,8 +26647,8 @@ async function checkGitCredentialHelper(ctx) {
26058
26647
  };
26059
26648
  }
26060
26649
  async function checkProjectConfig(ctx) {
26061
- const configPath = join53(ctx.cwd, ".runwork.json");
26062
- if (!existsSync56(configPath)) {
26650
+ const configPath = join54(ctx.cwd, ".runwork.json");
26651
+ if (!existsSync57(configPath)) {
26063
26652
  if (!ctx.credentials) {
26064
26653
  return { name: "project-config", status: "skip", message: "no project (not logged in)" };
26065
26654
  }
@@ -26121,7 +26710,7 @@ async function checkGitRemote(ctx) {
26121
26710
  if (!ctx.config) {
26122
26711
  return { name: "git-remote", status: "skip", message: "skipped (no project)" };
26123
26712
  }
26124
- if (!existsSync56(join53(ctx.cwd, ".git"))) {
26713
+ if (!existsSync57(join54(ctx.cwd, ".git"))) {
26125
26714
  return {
26126
26715
  name: "git-remote",
26127
26716
  status: "fail",
@@ -26175,12 +26764,12 @@ async function checkDeployFreshness(ctx) {
26175
26764
  return { name: "deploy-freshness", status: "skip", message: "local HEAD unknown" };
26176
26765
  }
26177
26766
  function loadSetupState5() {
26178
- const projectPath = join53(process.cwd(), ".runwork", "setup.json");
26179
- const userPath = join53(homedir32(), ".runwork", "setup.json");
26767
+ const projectPath = join54(process.cwd(), ".runwork", "setup.json");
26768
+ const userPath = join54(homedir33(), ".runwork", "setup.json");
26180
26769
  for (const p of [projectPath, userPath]) {
26181
- if (existsSync56(p)) {
26770
+ if (existsSync57(p)) {
26182
26771
  try {
26183
- return JSON.parse(readFileSync46(p, "utf-8"));
26772
+ return JSON.parse(readFileSync47(p, "utf-8"));
26184
26773
  } catch {
26185
26774
  continue;
26186
26775
  }
@@ -26195,13 +26784,13 @@ async function checkCodexNetwork() {
26195
26784
  if (!state || !state.configuredAgents.includes("codex")) {
26196
26785
  return { name, status: "skip", message: "Codex not configured for Runwork" };
26197
26786
  }
26198
- const configPath = join53(homedir32(), ".codex", "config.toml");
26199
- if (!existsSync56(configPath)) {
26787
+ const configPath = join54(homedir33(), ".codex", "config.toml");
26788
+ if (!existsSync57(configPath)) {
26200
26789
  return { name, status: "skip", message: "no Codex config found" };
26201
26790
  }
26202
26791
  let parsed;
26203
26792
  try {
26204
- parsed = parse2(readFileSync46(configPath, "utf-8"));
26793
+ parsed = parse2(readFileSync47(configPath, "utf-8"));
26205
26794
  } catch {
26206
26795
  return { name, status: "warn", message: "could not parse ~/.codex/config.toml" };
26207
26796
  }
@@ -26254,19 +26843,19 @@ async function checkCodexDesktopProject() {
26254
26843
  if (!usesCodex) {
26255
26844
  return { name, status: "skip", message: "Codex not configured for Runwork" };
26256
26845
  }
26257
- const statePath2 = join53(homedir32(), ".codex", ".codex-global-state.json");
26258
- if (!existsSync56(statePath2)) {
26846
+ const statePath2 = join54(homedir33(), ".codex", ".codex-global-state.json");
26847
+ if (!existsSync57(statePath2)) {
26259
26848
  return { name, status: "skip", message: "Codex desktop app not detected" };
26260
26849
  }
26261
26850
  let savedRoots = [];
26262
26851
  try {
26263
- const parsed = JSON.parse(readFileSync46(statePath2, "utf-8"));
26852
+ const parsed = JSON.parse(readFileSync47(statePath2, "utf-8"));
26264
26853
  const roots = parsed["electron-saved-workspace-roots"];
26265
26854
  savedRoots = Array.isArray(roots) ? roots.filter((r) => typeof r === "string") : [];
26266
26855
  } catch {
26267
26856
  return { name, status: "warn", message: "could not read Codex desktop state" };
26268
26857
  }
26269
- const runworkDir = join53(homedir32(), ".runwork");
26858
+ const runworkDir = join54(homedir33(), ".runwork");
26270
26859
  if (savedRoots.includes(runworkDir)) {
26271
26860
  return { name, status: "pass", message: "Runwork project added to Codex desktop sidebar" };
26272
26861
  }
@@ -26320,9 +26909,9 @@ async function checkAgentSetup() {
26320
26909
  if (!adapter2 || !adapter2.supportsMcpScope("user"))
26321
26910
  continue;
26322
26911
  const mcpConfigPath = getMcpConfigPath2(slug, "user");
26323
- if (mcpConfigPath && existsSync56(mcpConfigPath)) {
26912
+ if (mcpConfigPath && existsSync57(mcpConfigPath)) {
26324
26913
  try {
26325
- const content = readFileSync46(mcpConfigPath, "utf-8");
26914
+ const content = readFileSync47(mcpConfigPath, "utf-8");
26326
26915
  const missingMcp = state.mcpServers.filter((name) => !content.includes(name));
26327
26916
  if (missingMcp.length > 0) {
26328
26917
  details.push(`${missingMcp.length} MCP server(s) missing from ${slug} config`);
@@ -26353,8 +26942,8 @@ async function checkAgentSetup() {
26353
26942
  const missingSkills = state.skills.filter((name) => {
26354
26943
  if (isCoveredByMcp(name))
26355
26944
  return false;
26356
- const skillPath = join53(skillsDir, name, "SKILL.md");
26357
- return !existsSync56(skillPath);
26945
+ const skillPath = join54(skillsDir, name, "SKILL.md");
26946
+ return !existsSync57(skillPath);
26358
26947
  });
26359
26948
  if (missingSkills.length > 0) {
26360
26949
  details.push(`${missingSkills.length} skill(s) missing from ${slug}`);
@@ -26384,28 +26973,28 @@ async function checkAgentSetup() {
26384
26973
  };
26385
26974
  }
26386
26975
  function getMcpConfigPath2(slug, scope) {
26387
- const home = homedir32();
26976
+ const home2 = homedir33();
26388
26977
  switch (slug) {
26389
26978
  case "claude-code":
26390
- return scope === "project" ? join53(process.cwd(), ".mcp.json") : join53(home, ".claude", "settings.json");
26979
+ return scope === "project" ? join54(process.cwd(), ".mcp.json") : join54(home2, ".claude", "settings.json");
26391
26980
  case "cursor":
26392
- return scope === "project" ? join53(process.cwd(), ".cursor", "mcp.json") : join53(home, ".cursor", "mcp.json");
26981
+ return scope === "project" ? join54(process.cwd(), ".cursor", "mcp.json") : join54(home2, ".cursor", "mcp.json");
26393
26982
  case "windsurf":
26394
- return scope === "project" ? join53(process.cwd(), ".windsurf", "mcp.json") : join53(home, ".windsurf", "mcp.json");
26983
+ return scope === "project" ? join54(process.cwd(), ".windsurf", "mcp.json") : join54(home2, ".windsurf", "mcp.json");
26395
26984
  case "codex":
26396
26985
  case "codex-app":
26397
- return scope === "user" ? join53(home, ".codex", "config.toml") : null;
26986
+ return scope === "user" ? join54(home2, ".codex", "config.toml") : null;
26398
26987
  case "gemini":
26399
- return scope === "user" ? join53(home, ".gemini", "settings.json") : null;
26988
+ return scope === "user" ? join54(home2, ".gemini", "settings.json") : null;
26400
26989
  default:
26401
26990
  return null;
26402
26991
  }
26403
26992
  }
26404
26993
  async function checkWorkspacePointers() {
26405
- const userStatePath = join53(homedir32(), ".runwork", "setup.json");
26406
- const state = existsSync56(userStatePath) ? (() => {
26994
+ const userStatePath = join54(homedir33(), ".runwork", "setup.json");
26995
+ const state = existsSync57(userStatePath) ? (() => {
26407
26996
  try {
26408
- return JSON.parse(readFileSync46(userStatePath, "utf-8"));
26997
+ return JSON.parse(readFileSync47(userStatePath, "utf-8"));
26409
26998
  } catch {
26410
26999
  return null;
26411
27000
  }
@@ -26435,15 +27024,15 @@ async function checkWorkspacePointers() {
26435
27024
  };
26436
27025
  }
26437
27026
  function getSkillsDir(slug, scope) {
26438
- const home = homedir32();
27027
+ const home2 = homedir33();
26439
27028
  switch (slug) {
26440
27029
  case "claude-code":
26441
- return scope === "project" ? join53(process.cwd(), ".claude", "skills") : join53(home, ".claude", "skills");
27030
+ return scope === "project" ? join54(process.cwd(), ".claude", "skills") : join54(home2, ".claude", "skills");
26442
27031
  case "codex":
26443
27032
  case "codex-app":
26444
- return scope === "project" ? join53(process.cwd(), ".agents", "skills") : join53(home, ".agents", "skills");
27033
+ return scope === "project" ? join54(process.cwd(), ".agents", "skills") : join54(home2, ".agents", "skills");
26445
27034
  case "gemini":
26446
- return scope === "project" ? join53(process.cwd(), ".gemini", "skills") : join53(home, ".gemini", "skills");
27035
+ return scope === "project" ? join54(process.cwd(), ".gemini", "skills") : join54(home2, ".gemini", "skills");
26447
27036
  default:
26448
27037
  return null;
26449
27038
  }
@@ -26496,8 +27085,8 @@ async function runAllChecks(options) {
26496
27085
  // src/health/fix.ts
26497
27086
  init_credentials();
26498
27087
  init_remote();
26499
- import { existsSync as existsSync57 } from "fs";
26500
- import { join as join54 } from "path";
27088
+ import { existsSync as existsSync58 } from "fs";
27089
+ import { join as join55 } from "path";
26501
27090
  async function applyDoctorFixes(ctx, failingNames) {
26502
27091
  const failing = new Set(failingNames);
26503
27092
  const outcomes = [];
@@ -26524,7 +27113,7 @@ async function applyDoctorFixes(ctx, failingNames) {
26524
27113
  applied: false,
26525
27114
  message: "no project config -- run inside an app directory"
26526
27115
  });
26527
- } else if (!existsSync57(join54(ctx.cwd, ".git"))) {
27116
+ } else if (!existsSync58(join55(ctx.cwd, ".git"))) {
26528
27117
  outcomes.push({
26529
27118
  name: "git-remote",
26530
27119
  applied: false,
@@ -26543,10 +27132,10 @@ async function applyDoctorFixes(ctx, failingNames) {
26543
27132
  }
26544
27133
 
26545
27134
  // src/agents/runtime-detection.ts
26546
- import { existsSync as existsSync58, readFileSync as readFileSync47, statSync as statSync11, readdirSync as readdirSync17 } from "fs";
26547
- import { homedir as homedir33 } from "os";
26548
- import { join as join55 } from "path";
26549
- var RUNWORK_SESSIONS_DIR = join55(homedir33(), ".runwork", "sessions");
27135
+ import { existsSync as existsSync59, readFileSync as readFileSync48, statSync as statSync12, readdirSync as readdirSync18 } from "fs";
27136
+ import { homedir as homedir34 } from "os";
27137
+ import { join as join56 } from "path";
27138
+ var RUNWORK_SESSIONS_DIR = join56(homedir34(), ".runwork", "sessions");
26550
27139
  function detectCurrentAgent() {
26551
27140
  const claudeCodeSessionId = process.env.CLAUDE_CODE_SESSION_ID;
26552
27141
  if (claudeCodeSessionId) {
@@ -26609,11 +27198,11 @@ function detectCurrentAgent() {
26609
27198
  return null;
26610
27199
  }
26611
27200
  function readHookSessionInfo(sessionId) {
26612
- const path4 = join55(RUNWORK_SESSIONS_DIR, `${sessionId}.json`);
26613
- if (!existsSync58(path4))
27201
+ const path4 = join56(RUNWORK_SESSIONS_DIR, `${sessionId}.json`);
27202
+ if (!existsSync59(path4))
26614
27203
  return null;
26615
27204
  try {
26616
- const raw = readFileSync47(path4, "utf8");
27205
+ const raw = readFileSync48(path4, "utf8");
26617
27206
  const parsed = JSON.parse(raw);
26618
27207
  return parsed;
26619
27208
  } catch {
@@ -26621,40 +27210,40 @@ function readHookSessionInfo(sessionId) {
26621
27210
  }
26622
27211
  }
26623
27212
  function findClaudeCodeSessionFile(sessionId) {
26624
- const root = join55(homedir33(), ".claude", "projects");
26625
- if (!existsSync58(root))
27213
+ const root = join56(homedir34(), ".claude", "projects");
27214
+ if (!existsSync59(root))
26626
27215
  return null;
26627
27216
  let projectDirs;
26628
27217
  try {
26629
- projectDirs = readdirSync17(root);
27218
+ projectDirs = readdirSync18(root);
26630
27219
  } catch {
26631
27220
  return null;
26632
27221
  }
26633
27222
  for (const dir of projectDirs) {
26634
- const candidate = join55(root, dir, `${sessionId}.jsonl`);
26635
- if (existsSync58(candidate))
27223
+ const candidate = join56(root, dir, `${sessionId}.jsonl`);
27224
+ if (existsSync59(candidate))
26636
27225
  return candidate;
26637
27226
  }
26638
27227
  return null;
26639
27228
  }
26640
27229
  function findCodexRolloutFile(threadId) {
26641
- const root = join55(homedir33(), ".codex", "sessions");
26642
- if (!existsSync58(root))
27230
+ const root = join56(homedir34(), ".codex", "sessions");
27231
+ if (!existsSync59(root))
26643
27232
  return null;
26644
27233
  const stack = [root];
26645
27234
  while (stack.length > 0) {
26646
27235
  const dir = stack.pop();
26647
27236
  let entries;
26648
27237
  try {
26649
- entries = readdirSync17(dir);
27238
+ entries = readdirSync18(dir);
26650
27239
  } catch {
26651
27240
  continue;
26652
27241
  }
26653
27242
  for (const entry of entries) {
26654
- const full = join55(dir, entry);
27243
+ const full = join56(dir, entry);
26655
27244
  let s;
26656
27245
  try {
26657
- s = statSync11(full);
27246
+ s = statSync12(full);
26658
27247
  } catch {
26659
27248
  continue;
26660
27249
  }
@@ -26668,30 +27257,30 @@ function findCodexRolloutFile(threadId) {
26668
27257
  return null;
26669
27258
  }
26670
27259
  function findNewestClaudeCodeSession() {
26671
- const root = join55(homedir33(), ".claude", "projects");
26672
- if (!existsSync58(root))
27260
+ const root = join56(homedir34(), ".claude", "projects");
27261
+ if (!existsSync59(root))
26673
27262
  return null;
26674
27263
  let projectDirs;
26675
27264
  try {
26676
- projectDirs = readdirSync17(root);
27265
+ projectDirs = readdirSync18(root);
26677
27266
  } catch {
26678
27267
  return null;
26679
27268
  }
26680
27269
  let best = null;
26681
27270
  for (const dir of projectDirs) {
26682
- const projectPath = join55(root, dir);
27271
+ const projectPath = join56(root, dir);
26683
27272
  let files;
26684
27273
  try {
26685
- files = readdirSync17(projectPath);
27274
+ files = readdirSync18(projectPath);
26686
27275
  } catch {
26687
27276
  continue;
26688
27277
  }
26689
27278
  for (const file of files) {
26690
27279
  if (!file.endsWith(".jsonl"))
26691
27280
  continue;
26692
- const full = join55(projectPath, file);
27281
+ const full = join56(projectPath, file);
26693
27282
  try {
26694
- const s = statSync11(full);
27283
+ const s = statSync12(full);
26695
27284
  if (!best || s.mtimeMs > best.mtime) {
26696
27285
  best = {
26697
27286
  sessionId: file.replace(/\.jsonl$/, ""),
@@ -26707,8 +27296,8 @@ function findNewestClaudeCodeSession() {
26707
27296
  return best ? { sessionId: best.sessionId, path: best.path } : null;
26708
27297
  }
26709
27298
  function findNewestCodexRollout() {
26710
- const root = join55(homedir33(), ".codex", "sessions");
26711
- if (!existsSync58(root))
27299
+ const root = join56(homedir34(), ".codex", "sessions");
27300
+ if (!existsSync59(root))
26712
27301
  return null;
26713
27302
  const stack = [root];
26714
27303
  let best = null;
@@ -26716,15 +27305,15 @@ function findNewestCodexRollout() {
26716
27305
  const dir = stack.pop();
26717
27306
  let entries;
26718
27307
  try {
26719
- entries = readdirSync17(dir);
27308
+ entries = readdirSync18(dir);
26720
27309
  } catch {
26721
27310
  continue;
26722
27311
  }
26723
27312
  for (const entry of entries) {
26724
- const full = join55(dir, entry);
27313
+ const full = join56(dir, entry);
26725
27314
  let s;
26726
27315
  try {
26727
- s = statSync11(full);
27316
+ s = statSync12(full);
26728
27317
  } catch {
26729
27318
  continue;
26730
27319
  }
@@ -26951,11 +27540,13 @@ var doctorCommand = new Command34("doctor").description("Check system health: au
26951
27540
  // src/commands/debug.ts
26952
27541
  init_colors();
26953
27542
  import { Command as Command35 } from "commander";
26954
- import { readFileSync as readFileSync48 } from "fs";
26955
- import { homedir as homedir35, platform as platform7, release, arch, type as osType } from "os";
26956
- import { join as join58 } from "path";
27543
+ import { readFileSync as readFileSync49 } from "fs";
27544
+ import { homedir as homedir36, platform as platform9, release, arch, type as osType } from "os";
27545
+ import { join as join59 } from "path";
26957
27546
 
26958
27547
  // src/debug/capture-plan.ts
27548
+ init_transcript_stores();
27549
+ init_registry_data();
26959
27550
  var CONFIG_MAX_BYTES = 64 * 1024;
26960
27551
  var LOG_TAIL_BYTES = 64 * 1024;
26961
27552
  var CENSUS_MAX_ENTRIES = 200;
@@ -26981,9 +27572,9 @@ var ENV_NAMES = [
26981
27572
  ];
26982
27573
  function buildCapturePlan(input) {
26983
27574
  const sep5 = input.sep ?? (input.platform === "win32" ? "\\" : "/");
26984
- const join56 = (...parts) => parts.join(sep5);
26985
- const home = input.homeDir.replace(/[/\\]+$/, "");
26986
- const rw = (...parts) => join56(home, ".runwork", ...parts);
27575
+ const join57 = (...parts) => parts.join(sep5);
27576
+ const home2 = input.homeDir.replace(/[/\\]+$/, "");
27577
+ const rw = (...parts) => join57(home2, ".runwork", ...parts);
26987
27578
  const steps = [];
26988
27579
  steps.push({ id: "env", kind: "env", names: ENV_NAMES, note: "process environment (proxy credentials stripped)" });
26989
27580
  for (const [id, file] of [
@@ -27013,62 +27604,129 @@ function buildCapturePlan(input) {
27013
27604
  ["codex.agents-md", ".codex", "AGENTS.md"],
27014
27605
  ["gemini.settings", ".gemini", "settings.json"]
27015
27606
  ]) {
27016
- steps.push({ id, kind: "file", path: join56(home, ...parts), maxBytes: CONFIG_MAX_BYTES });
27017
- }
27607
+ steps.push({ id, kind: "file", path: join57(home2, ...parts), maxBytes: CONFIG_MAX_BYTES });
27608
+ }
27609
+ steps.push({
27610
+ id: "claude.desktop-config",
27611
+ kind: "file",
27612
+ path: join57(appDataRootFor(input, join57), "Claude", "claude_desktop_config.json"),
27613
+ maxBytes: CONFIG_MAX_BYTES,
27614
+ note: "the MCP config we write for Claude Desktop, next to its session store"
27615
+ });
27616
+ steps.push({
27617
+ id: "codex.version",
27618
+ kind: "file",
27619
+ path: join57(home2, ".codex", "version.json"),
27620
+ maxBytes: 4096,
27621
+ note: "Codex build, for placing an unrecognised originator value"
27622
+ });
27018
27623
  for (const [id, ...parts] of [
27019
27624
  ["claude.skills", ".claude", "skills"],
27020
27625
  ["claude.plugins", ".claude", "plugins"],
27021
27626
  ["agents.skills", ".agents", "skills"],
27022
27627
  ["codex.skills", ".codex", "skills"]
27023
27628
  ]) {
27024
- steps.push({ id, kind: "census", path: join56(home, ...parts), depth: 1, maxEntries: CENSUS_MAX_ENTRIES });
27629
+ steps.push({ id, kind: "census", path: join57(home2, ...parts), depth: 1, maxEntries: CENSUS_MAX_ENTRIES });
27630
+ }
27631
+ for (const store of resolveTranscriptStores({
27632
+ platform: input.platform,
27633
+ homeDir: home2,
27634
+ sep: sep5,
27635
+ appData: input.appData,
27636
+ localAppData: input.localAppData
27637
+ })) {
27638
+ const id = `stores.${store.def.id.replace(/\//g, ".")}`;
27639
+ steps.push(store.def.kind === "file" ? { id, kind: "stat", path: store.path, ...store.def.note ? { note: store.def.note } : {} } : { id, kind: "census", path: store.path, depth: 2, maxEntries: CENSUS_MAX_ENTRIES, ...store.def.note ? { note: store.def.note } : {} });
27640
+ for (const parent of parentsWorthProbing(store.path, sep5)) {
27641
+ steps.push({ id: `${id}.parent`, kind: "census", path: parent, depth: 1, maxEntries: 50, note: "is the vendor directory there at all" });
27642
+ }
27643
+ store.altPaths.forEach((alt, i) => {
27644
+ steps.push({ id: `${id}.alt${i}`, kind: "stat", path: alt, note: "alternate location; a hit means the canonical path is wrong here" });
27645
+ });
27646
+ }
27647
+ if (input.platform === "win32") {
27648
+ steps.push({
27649
+ id: "windows.appx-packages",
27650
+ kind: "census",
27651
+ path: join57(input.localAppData ?? join57(home2, "AppData", "Local"), "Packages"),
27652
+ depth: 1,
27653
+ maxEntries: CENSUS_MAX_ENTRIES,
27654
+ note: "AppX package identities: an MSIX agent can virtualize its writes in here"
27655
+ });
27025
27656
  }
27026
- steps.push({ id: "transcripts.claude-code", kind: "census", path: join56(home, ".claude", "projects"), depth: 1, maxEntries: CENSUS_MAX_ENTRIES }, { id: "transcripts.codex", kind: "census", path: join56(home, ".codex", "sessions"), depth: 2, maxEntries: CENSUS_MAX_ENTRIES }, { id: "transcripts.gemini", kind: "census", path: join56(home, ".gemini", "tmp"), depth: 1, maxEntries: CENSUS_MAX_ENTRIES }, { id: "transcripts.cowork", kind: "census", path: coworkBaseDir(input, join56), depth: 1, maxEntries: CENSUS_MAX_ENTRIES, note: "macOS TCC can refuse this while it still exists" });
27027
27657
  for (const profile of shellProfiles(input.platform)) {
27028
27658
  steps.push({
27029
27659
  id: `shell${profile}`,
27030
27660
  kind: "stat",
27031
- path: join56(home, profile),
27661
+ path: join57(home2, profile),
27032
27662
  note: "presence only: profile bodies can contain the user's own secrets"
27033
27663
  });
27034
27664
  }
27035
27665
  steps.push(...binaryResolutionSteps(input));
27666
+ steps.push(...agentBinaryProbes(input));
27036
27667
  if (input.cliPath) {
27037
- steps.push({ id: "cli.version", kind: "exec", command: input.cliPath, args: ["--version"] }, { id: "cli.doctor", kind: "exec", command: input.cliPath, args: ["--json", "doctor", "-v"] }, { id: "cli.conversations", kind: "exec", command: input.cliPath, args: ["--json", "conversations", "status", "--days", "0"], note: "per-agent scan outcome, no conversation data" });
27668
+ steps.push({ id: "cli.version", kind: "exec", command: input.cliPath, args: ["--version"] }, { id: "cli.doctor", kind: "exec", command: input.cliPath, args: ["--json", "doctor", "-v"] }, { id: "cli.conversations", kind: "exec", command: input.cliPath, args: ["--json", "conversations", "status", "--days", "0"], note: "per-agent scan outcome, no conversation data" }, { id: "cli.stores", kind: "exec", command: input.cliPath, args: ["--json", "conversations", "stores"], note: "per-store contents and provenance, no conversation text" });
27038
27669
  }
27039
27670
  return steps;
27040
27671
  }
27041
- function coworkBaseDir(input, join56) {
27042
- const home = input.homeDir.replace(/[/\\]+$/, "");
27043
- if (input.platform === "darwin") {
27044
- return join56(home, "Library", "Application Support", "Claude", "local-agent-mode-sessions");
27045
- }
27046
- if (input.platform === "win32") {
27047
- const base = input.appData ?? join56(home, "AppData", "Roaming");
27048
- return join56(base, "Claude", "local-agent-mode-sessions");
27672
+ function parentsWorthProbing(storePath4, sep5) {
27673
+ const idx = storePath4.lastIndexOf(sep5);
27674
+ if (idx <= 0)
27675
+ return [];
27676
+ const parent = storePath4.slice(0, idx);
27677
+ const parentIdx = parent.lastIndexOf(sep5);
27678
+ if (parentIdx <= 0)
27679
+ return [];
27680
+ return [parent];
27681
+ }
27682
+ function agentBinaryProbes(input) {
27683
+ const finder = input.platform === "win32" ? "where.exe" : "which";
27684
+ const args = (binary) => input.platform === "win32" ? [binary] : ["-a", binary];
27685
+ const seen = new Set;
27686
+ const steps = [];
27687
+ for (const agent of getDetectableAgents()) {
27688
+ const binary = agent.launch?.cli;
27689
+ if (!binary || seen.has(binary))
27690
+ continue;
27691
+ seen.add(binary);
27692
+ steps.push({
27693
+ id: `agent-binary.${agent.slug}`,
27694
+ kind: "exec",
27695
+ command: finder,
27696
+ args: args(binary),
27697
+ note: `is ${agent.name}'s CLI on PATH, and where`
27698
+ });
27049
27699
  }
27050
- return join56(home, ".config", "Claude", "local-agent-mode-sessions");
27700
+ return steps;
27701
+ }
27702
+ function appDataRootFor(input, join57) {
27703
+ const home2 = input.homeDir.replace(/[/\\]+$/, "");
27704
+ if (input.platform === "darwin")
27705
+ return join57(home2, "Library", "Application Support");
27706
+ if (input.platform === "win32")
27707
+ return input.appData ?? join57(home2, "AppData", "Roaming");
27708
+ return join57(home2, ".config");
27051
27709
  }
27052
- function shellProfiles(platform7) {
27053
- if (platform7 === "win32")
27710
+ function shellProfiles(platform9) {
27711
+ if (platform9 === "win32")
27054
27712
  return [];
27055
27713
  return [".zshrc", ".zprofile", ".bashrc", ".bash_profile", ".profile"];
27056
27714
  }
27057
27715
  function binaryResolutionSteps(input) {
27058
27716
  const sep5 = input.sep ?? (input.platform === "win32" ? "\\" : "/");
27059
- const join56 = (...parts) => parts.join(sep5);
27060
- const home = input.homeDir.replace(/[/\\]+$/, "");
27717
+ const join57 = (...parts) => parts.join(sep5);
27718
+ const home2 = input.homeDir.replace(/[/\\]+$/, "");
27061
27719
  if (input.platform === "win32") {
27062
27720
  return [
27063
27721
  { id: "binaries.where", kind: "exec", command: "where.exe", args: ["runwork"], note: "every match, not just the first" },
27064
- { id: "binaries.runwork-bin", kind: "stat", path: join56(home, ".runwork", "bin", "runwork.exe") },
27722
+ { id: "binaries.runwork-bin", kind: "stat", path: join57(home2, ".runwork", "bin", "runwork.exe") },
27065
27723
  { id: "binaries.user-path", kind: "exec", command: "reg.exe", args: ["query", "HKCU\\Environment", "/v", "Path"], note: "the PATH a NEW shell will inherit, not this one" }
27066
27724
  ];
27067
27725
  }
27068
27726
  return [
27069
27727
  { id: "binaries.which", kind: "exec", command: "which", args: ["-a", "runwork"], note: "every match, not just the first" },
27070
- { id: "binaries.runwork-bin", kind: "stat", path: join56(home, ".runwork", "bin", "runwork") },
27071
- { id: "binaries.local-bin", kind: "stat", path: join56(home, ".local", "bin", "runwork") },
27728
+ { id: "binaries.runwork-bin", kind: "stat", path: join57(home2, ".runwork", "bin", "runwork") },
27729
+ { id: "binaries.local-bin", kind: "stat", path: join57(home2, ".local", "bin", "runwork") },
27072
27730
  ...input.platform === "darwin" ? [{ id: "binaries.usr-local-bin", kind: "stat", path: "/usr/local/bin/runwork" }] : []
27073
27731
  ];
27074
27732
  }
@@ -27284,10 +27942,10 @@ async function runCapture(port, producer, steps, opts = {}) {
27284
27942
  // src/utils/machine-id.ts
27285
27943
  init_atomic_json();
27286
27944
  import { randomUUID } from "crypto";
27287
- import { homedir as homedir34 } from "os";
27288
- import { join as join56 } from "path";
27945
+ import { homedir as homedir35 } from "os";
27946
+ import { join as join57 } from "path";
27289
27947
  function machineIdPath() {
27290
- return join56(homedir34(), ".runwork", "machine.json");
27948
+ return join57(homedir35(), ".runwork", "machine.json");
27291
27949
  }
27292
27950
  function isValidId(value) {
27293
27951
  return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
@@ -27315,8 +27973,8 @@ init_resolve();
27315
27973
  // src/debug/node-port.ts
27316
27974
  init_subprocess();
27317
27975
  init_which();
27318
- import { closeSync as closeSync5, fsyncSync, mkdirSync as mkdirSync29, openSync as openSync5, readSync as readSync3, readdirSync as readdirSync18, statSync as statSync12, writeSync } from "fs";
27319
- import { dirname as dirname12, join as join57 } from "path";
27976
+ import { closeSync as closeSync6, fsyncSync, mkdirSync as mkdirSync29, openSync as openSync6, readSync as readSync4, readdirSync as readdirSync19, statSync as statSync13, writeSync } from "fs";
27977
+ import { dirname as dirname12, join as join58 } from "path";
27320
27978
  var EXEC_OUTPUT_MAX = 256 * 1024;
27321
27979
  var EXEC_TIMEOUT_MS = 20000;
27322
27980
  function truncate5(text2, maxBytes) {
@@ -27324,7 +27982,7 @@ function truncate5(text2, maxBytes) {
27324
27982
  }
27325
27983
  function entryKind(path4) {
27326
27984
  try {
27327
- const s = statSync12(path4);
27985
+ const s = statSync13(path4);
27328
27986
  return s.isDirectory() ? "dir" : s.isFile() ? "file" : "other";
27329
27987
  } catch {
27330
27988
  return "other";
@@ -27332,9 +27990,9 @@ function entryKind(path4) {
27332
27990
  }
27333
27991
  function createNodeCapturePort(outputPath) {
27334
27992
  mkdirSync29(dirname12(outputPath), { recursive: true });
27335
- const fd = openSync5(outputPath, "w");
27993
+ const fd = openSync6(outputPath, "w");
27336
27994
  return {
27337
- close: () => closeSync5(fd),
27995
+ close: () => closeSync6(fd),
27338
27996
  async append(record) {
27339
27997
  writeSync(fd, JSON.stringify(record) + `
27340
27998
  `);
@@ -27350,7 +28008,7 @@ function createNodeCapturePort(outputPath) {
27350
28008
  const { dir, prefix, level } = queue.shift();
27351
28009
  let names;
27352
28010
  try {
27353
- names = readdirSync18(dir);
28011
+ names = readdirSync19(dir);
27354
28012
  } catch (err) {
27355
28013
  if (first)
27356
28014
  throw err;
@@ -27361,12 +28019,12 @@ function createNodeCapturePort(outputPath) {
27361
28019
  for (const name of names) {
27362
28020
  if (out.length >= maxEntries)
27363
28021
  break;
27364
- const full = join57(dir, name);
28022
+ const full = join58(dir, name);
27365
28023
  const kind = entryKind(full);
27366
28024
  let bytes;
27367
28025
  let modifiedAt;
27368
28026
  try {
27369
- const s = statSync12(full);
28027
+ const s = statSync13(full);
27370
28028
  bytes = s.size;
27371
28029
  modifiedAt = new Date(s.mtimeMs).toISOString();
27372
28030
  } catch {}
@@ -27379,7 +28037,7 @@ function createNodeCapturePort(outputPath) {
27379
28037
  return out;
27380
28038
  },
27381
28039
  async stat(path4) {
27382
- const s = statSync12(path4);
28040
+ const s = statSync13(path4);
27383
28041
  return {
27384
28042
  bytes: s.size,
27385
28043
  modifiedAt: new Date(s.mtimeMs).toISOString(),
@@ -27387,16 +28045,16 @@ function createNodeCapturePort(outputPath) {
27387
28045
  };
27388
28046
  },
27389
28047
  async readText(path4, maxBytes, tail) {
27390
- const s = statSync12(path4);
28048
+ const s = statSync13(path4);
27391
28049
  const size = s.size;
27392
28050
  const length = Math.min(size, maxBytes);
27393
28051
  const start = tail && size > maxBytes ? size - maxBytes : 0;
27394
28052
  const buffer = Buffer.alloc(length);
27395
- const handle = openSync5(path4, "r");
28053
+ const handle = openSync6(path4, "r");
27396
28054
  try {
27397
- readSync3(handle, buffer, 0, length, start);
28055
+ readSync4(handle, buffer, 0, length, start);
27398
28056
  } finally {
27399
- closeSync5(handle);
28057
+ closeSync6(handle);
27400
28058
  }
27401
28059
  return { text: buffer.toString("utf-8"), truncated: size > length };
27402
28060
  },
@@ -27429,7 +28087,7 @@ init_which();
27429
28087
  await init_detect();
27430
28088
  function defaultOutputPath(now) {
27431
28089
  const stamp = now.toISOString().replace(/[:.]/g, "-").replace("T", "_").slice(0, 19);
27432
- return join58(homedir35(), ".runwork", "debug", `runwork-debug-${stamp}.jsonl`);
28090
+ return join59(homedir36(), ".runwork", "debug", `runwork-debug-${stamp}.jsonl`);
27433
28091
  }
27434
28092
  async function cliClaims() {
27435
28093
  const records = [];
@@ -27442,7 +28100,7 @@ async function cliClaims() {
27442
28100
  execPath: process.execPath,
27443
28101
  argv0: process.argv[1] ?? null,
27444
28102
  nodeVersion: process.version,
27445
- platform: platform7(),
28103
+ platform: platform9(),
27446
28104
  osType: osType(),
27447
28105
  release: release(),
27448
28106
  arch: arch(),
@@ -27482,9 +28140,10 @@ debugCommand.command("capture").description("Collect a diagnostic bundle to a fi
27482
28140
  const outputPath = typeof opts.out === "string" && opts.out ? opts.out : defaultOutputPath(new Date);
27483
28141
  const cliPath = whichBinary("runwork");
27484
28142
  const plan = buildCapturePlan({
27485
- platform: platform7(),
27486
- homeDir: homedir35(),
28143
+ platform: platform9(),
28144
+ homeDir: homedir36(),
27487
28145
  appData: process.env.APPDATA ?? null,
28146
+ localAppData: process.env.LOCALAPPDATA ?? null,
27488
28147
  cliPath
27489
28148
  });
27490
28149
  if (!json) {
@@ -27528,7 +28187,7 @@ Done. ${counted} checks recorded.`));
27528
28187
  });
27529
28188
  async function sendBundle(path4, note) {
27530
28189
  try {
27531
- const content = readFileSync48(path4, "utf-8");
28190
+ const content = readFileSync49(path4, "utf-8");
27532
28191
  const summary = summarizeBundle(content);
27533
28192
  const machineId = getMachineId();
27534
28193
  if (!machineId)
@@ -27547,7 +28206,7 @@ async function sendBundle(path4, note) {
27547
28206
  ...note ? { note } : {},
27548
28207
  context: {
27549
28208
  cliVersion: VERSION,
27550
- platform: platform7(),
28209
+ platform: platform9(),
27551
28210
  release: release(),
27552
28211
  stepsPlanned: summary.stepsPlanned,
27553
28212
  stepsRun: summary.stepsRun,
@@ -27567,8 +28226,8 @@ init_store();
27567
28226
  init_client();
27568
28227
  init_resolve();
27569
28228
  import { Command as Command36 } from "commander";
27570
- import { readFileSync as readFileSync49, writeFileSync as writeFileSync33, existsSync as existsSync59, mkdtempSync as mkdtempSync4 } from "fs";
27571
- import { join as join59 } from "path";
28229
+ import { readFileSync as readFileSync50, writeFileSync as writeFileSync33, existsSync as existsSync60, mkdtempSync as mkdtempSync4 } from "fs";
28230
+ import { join as join60 } from "path";
27572
28231
  import { tmpdir as tmpdir4 } from "os";
27573
28232
  import { createHash as createHash6 } from "crypto";
27574
28233
 
@@ -27690,13 +28349,13 @@ function resolveLocalSessionShare(opts, conversation) {
27690
28349
  process.exit(1);
27691
28350
  }
27692
28351
  const title = opts.title ?? conversation.title ?? conversation.project;
27693
- const markdown = renderTranscriptMarkdown(readFileSync49(conversation.transcriptPath, "utf8"), family, title);
28352
+ const markdown = renderTranscriptMarkdown(readFileSync50(conversation.transcriptPath, "utf8"), family, title);
27694
28353
  if (!markdown) {
27695
28354
  console.error("Error: this conversation has no shareable content.");
27696
28355
  process.exit(1);
27697
28356
  }
27698
- const tempDir = mkdtempSync4(join59(tmpdir4(), "runwork-share-"));
27699
- const transcriptFile = join59(tempDir, "transcript.md");
28357
+ const tempDir = mkdtempSync4(join60(tmpdir4(), "runwork-share-"));
28358
+ const transcriptFile = join60(tempDir, "transcript.md");
27700
28359
  writeFileSync33(transcriptFile, markdown);
27701
28360
  opts.transcriptFile = transcriptFile;
27702
28361
  opts.nativeFile = opts.nativeFile ?? conversation.transcriptPath;
@@ -27734,7 +28393,7 @@ async function runShareConvo(opts, command, isPersonalAlias = false) {
27734
28393
  console.error("Error: --transcript-file is required. Pass the path to the LLM-emitted markdown transcript.");
27735
28394
  process.exit(1);
27736
28395
  }
27737
- if (!existsSync59(opts.transcriptFile)) {
28396
+ if (!existsSync60(opts.transcriptFile)) {
27738
28397
  console.error(`Error: transcript file does not exist: ${opts.transcriptFile}`);
27739
28398
  process.exit(1);
27740
28399
  }
@@ -27755,7 +28414,7 @@ async function runShareConvo(opts, command, isPersonalAlias = false) {
27755
28414
  const credentials = requireAuth();
27756
28415
  const client = new ApiClient(credentials);
27757
28416
  const { workspaceId } = await resolveWorkspace2(client, { workspace: opts.workspace });
27758
- const transcriptContent = readFileSync49(opts.transcriptFile, "utf8");
28417
+ const transcriptContent = readFileSync50(opts.transcriptFile, "utf8");
27759
28418
  const bundles = [
27760
28419
  {
27761
28420
  format: "transcript",
@@ -27768,19 +28427,19 @@ async function runShareConvo(opts, command, isPersonalAlias = false) {
27768
28427
  const sourceAgent = opts.sourceAgent ?? detected?.slug ?? "generic";
27769
28428
  let nativeFilePath = null;
27770
28429
  if (opts.nativeFile) {
27771
- if (!existsSync59(opts.nativeFile)) {
28430
+ if (!existsSync60(opts.nativeFile)) {
27772
28431
  console.error(`Error: --native-file path does not exist: ${opts.nativeFile}`);
27773
28432
  process.exit(1);
27774
28433
  }
27775
28434
  nativeFilePath = opts.nativeFile;
27776
- } else if (detected?.sessionFilePath && existsSync59(detected.sessionFilePath)) {
28435
+ } else if (detected?.sessionFilePath && existsSync60(detected.sessionFilePath)) {
27777
28436
  nativeFilePath = detected.sessionFilePath;
27778
28437
  }
27779
28438
  if (nativeFilePath) {
27780
28439
  const nativeFormat = nativeBundleFormatForAgent(sourceAgent);
27781
28440
  if (nativeFormat) {
27782
28441
  try {
27783
- const content = readFileSync49(nativeFilePath, "utf8");
28442
+ const content = readFileSync50(nativeFilePath, "utf8");
27784
28443
  bundles.push({
27785
28444
  format: nativeFormat,
27786
28445
  content,
@@ -27796,7 +28455,7 @@ async function runShareConvo(opts, command, isPersonalAlias = false) {
27796
28455
  let metadata = {};
27797
28456
  if (opts.metadataFile) {
27798
28457
  try {
27799
- metadata = JSON.parse(readFileSync49(opts.metadataFile, "utf8"));
28458
+ metadata = JSON.parse(readFileSync50(opts.metadataFile, "utf8"));
27800
28459
  } catch (err) {
27801
28460
  console.error(`Error: --metadata-file is not valid JSON: ${err instanceof Error ? err.message : err}`);
27802
28461
  process.exit(1);
@@ -27906,8 +28565,8 @@ init_resolve();
27906
28565
  init_registry_data();
27907
28566
  import { Command as Command39 } from "commander";
27908
28567
  import { writeFileSync as writeFileSync34, mkdirSync as mkdirSync30, realpathSync } from "fs";
27909
- import { homedir as homedir36 } from "os";
27910
- import { join as join60 } from "path";
28568
+ import { homedir as homedir37 } from "os";
28569
+ import { join as join61 } from "path";
27911
28570
  import { spawn as spawn5 } from "child_process";
27912
28571
  init_registry();
27913
28572
  init_which();
@@ -27946,9 +28605,9 @@ function extractCodexUuid(rolloutContent) {
27946
28605
  }
27947
28606
  function placeClaudeJsonl(uuid, content, recipientCwd) {
27948
28607
  const encoded = encodeClaudeCodeCwd(recipientCwd);
27949
- const projectDir = join60(homedir36(), ".claude", "projects", encoded);
28608
+ const projectDir = join61(homedir37(), ".claude", "projects", encoded);
27950
28609
  mkdirSync30(projectDir, { recursive: true });
27951
- const placedAt = join60(projectDir, `${uuid}.jsonl`);
28610
+ const placedAt = join61(projectDir, `${uuid}.jsonl`);
27952
28611
  writeFileSync34(placedAt, content);
27953
28612
  return { placedAt, runFromCwd: recipientCwd };
27954
28613
  }
@@ -27957,10 +28616,10 @@ function placeCodexRollout(uuid, content) {
27957
28616
  const yyyy = String(now.getUTCFullYear());
27958
28617
  const mm = String(now.getUTCMonth() + 1).padStart(2, "0");
27959
28618
  const dd = String(now.getUTCDate()).padStart(2, "0");
27960
- const dir = join60(homedir36(), ".codex", "sessions", yyyy, mm, dd);
28619
+ const dir = join61(homedir37(), ".codex", "sessions", yyyy, mm, dd);
27961
28620
  mkdirSync30(dir, { recursive: true });
27962
28621
  const ts = now.toISOString().replace(/\.\d+Z$/, "").replace(/:/g, "-");
27963
- const placedAt = join60(dir, `rollout-${ts}-${uuid}.jsonl`);
28622
+ const placedAt = join61(dir, `rollout-${ts}-${uuid}.jsonl`);
27964
28623
  writeFileSync34(placedAt, content);
27965
28624
  return { placedAt };
27966
28625
  }