@dosu/cli 0.63.0 → 0.64.1

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 (3) hide show
  1. package/README.md +5 -3
  2. package/bin/dosu.js +601 -361
  3. package/package.json +1 -1
package/bin/dosu.js CHANGED
@@ -1083,7 +1083,7 @@ function isNpxInvocation(channel = INSTALL_CHANNEL, env = process.env) {
1083
1083
  function getVersionString() {
1084
1084
  return `v${VERSION}`;
1085
1085
  }
1086
- var VERSION = "0.63.0", INSTALL_CHANNEL = "npm";
1086
+ var VERSION = "0.64.1", INSTALL_CHANNEL = "npm";
1087
1087
 
1088
1088
  // src/debug/logger.ts
1089
1089
  import {
@@ -1501,22 +1501,33 @@ function normalizeRepoRemote(remote) {
1501
1501
  const lowerHost = host.toLowerCase();
1502
1502
  return `${lowerHost}/${lowerHost === "github.com" ? path.toLowerCase() : path}`;
1503
1503
  }
1504
- function originRepoOfDir(dir) {
1504
+ function gitOutput(dir, args, timeout) {
1505
1505
  const env = { ...process.env };
1506
1506
  for (const name of GIT_LOCATION_ENV)
1507
1507
  delete env[name];
1508
1508
  try {
1509
- const out = execFileSync("git", ["-C", dir, "remote", "get-url", "origin"], {
1509
+ return execFileSync("git", ["-C", dir, ...args], {
1510
1510
  encoding: "utf-8",
1511
1511
  env,
1512
1512
  stdio: ["ignore", "pipe", "ignore"],
1513
- timeout: 1000
1513
+ timeout,
1514
+ maxBuffer: 16 * 1024 * 1024
1514
1515
  });
1515
- return normalizeRepoRemote(out);
1516
1516
  } catch {
1517
1517
  return null;
1518
1518
  }
1519
1519
  }
1520
+ function originRepoOfDir(dir) {
1521
+ const out = gitOutput(dir, ["remote", "get-url", "origin"], 1000);
1522
+ return out === null ? null : normalizeRepoRemote(out);
1523
+ }
1524
+ function currentBranchOfDir(dir) {
1525
+ const out = gitOutput(dir, ["symbolic-ref", "--short", "-q", "HEAD"], 1000)?.trim();
1526
+ return out ? out : null;
1527
+ }
1528
+ function headReflogOfDir(dir) {
1529
+ return gitOutput(dir, ["reflog", "show", "--date=unix", "--format=%gd%x09%gs", "HEAD"], 5000);
1530
+ }
1520
1531
  function displayRepo(repo) {
1521
1532
  return repo.split("/").slice(1).join("/") || repo;
1522
1533
  }
@@ -2079,8 +2090,11 @@ function filterSessionsByRepo(sessions, filter, resolveRepo) {
2079
2090
  const kept = [];
2080
2091
  for (const session of sessions) {
2081
2092
  const repo = resolveRepo(session);
2082
- if (repo !== null && (filter === null || filter.includes(repo)))
2093
+ if (repo !== null && (filter === null || filter.includes(repo))) {
2083
2094
  kept.push({ ...session, repo });
2095
+ } else if (filter === null) {
2096
+ kept.push(session);
2097
+ }
2084
2098
  }
2085
2099
  return kept;
2086
2100
  }
@@ -2138,15 +2152,12 @@ function defaultHookEnabled(agentId) {
2138
2152
  }
2139
2153
  }
2140
2154
  function cwdIsStudied(cwd, state, repoOfDir) {
2141
- if (!cwd)
2142
- return false;
2143
- const repo = repoOfDir(cwd);
2144
- if (!repo)
2145
- return false;
2146
- if (state.repo_filter)
2147
- return state.repo_filter.includes(repo);
2155
+ if (state.repo_filter) {
2156
+ const repo = cwd ? repoOfDir(cwd) : null;
2157
+ return repo !== null && state.repo_filter.includes(repo);
2158
+ }
2148
2159
  if (state.project_filter?.length) {
2149
- return state.project_filter.some((base) => isUnderDir(cwd, base));
2160
+ return cwd !== undefined && state.project_filter.some((base) => isUnderDir(cwd, base));
2150
2161
  }
2151
2162
  return true;
2152
2163
  }
@@ -11366,6 +11377,18 @@ var init_deployments = __esm(() => {
11366
11377
  import_picocolors15 = __toESM(require_picocolors(), 1);
11367
11378
  });
11368
11379
 
11380
+ // src/cli/errors.ts
11381
+ var CliUsageError;
11382
+ var init_errors = __esm(() => {
11383
+ CliUsageError = class CliUsageError extends Error {
11384
+ exitCode = 1;
11385
+ constructor(message) {
11386
+ super(message);
11387
+ this.name = "CliUsageError";
11388
+ }
11389
+ };
11390
+ });
11391
+
11369
11392
  // src/commands/doc-import.ts
11370
11393
  async function importDocuments(client, platform, context, ids) {
11371
11394
  const baseInput = {
@@ -11405,6 +11428,7 @@ var init_doc_import = __esm(() => {
11405
11428
 
11406
11429
  // src/commands/docs.ts
11407
11430
  import { readFileSync as readFileSync10 } from "node:fs";
11431
+ import { resolve } from "node:path";
11408
11432
  function requireConfig5() {
11409
11433
  const cfg = requireLoginConfig();
11410
11434
  if (!cfg.active_account?.target?.space_id) {
@@ -11424,9 +11448,21 @@ async function getKnowledgeStoreId(client, spaceId) {
11424
11448
  return store.id;
11425
11449
  }
11426
11450
  function readBody(opts) {
11427
- if (opts.bodyFile)
11428
- return readFileSync10(opts.bodyFile, "utf-8");
11429
- return opts.body;
11451
+ if (!opts.bodyFile)
11452
+ return opts.body;
11453
+ const path = opts.bodyFile;
11454
+ try {
11455
+ return readFileSync10(path, "utf-8");
11456
+ } catch (err) {
11457
+ const code = err.code;
11458
+ if (code === "ENOENT") {
11459
+ throw new CliUsageError(`--body-file not found: ${path} (looked in ${resolve(path)}). ` + "Check the path, or pass the content with --body.");
11460
+ }
11461
+ if (code === "EISDIR") {
11462
+ throw new CliUsageError(`--body-file is a directory, not a file: ${path}`);
11463
+ }
11464
+ throw new CliUsageError(`Could not read --body-file ${path}: ${err.message}`);
11465
+ }
11430
11466
  }
11431
11467
  function parseSerializedImportError(message) {
11432
11468
  let text = message;
@@ -11560,10 +11596,10 @@ ${page.body}`);
11560
11596
  }
11561
11597
  });
11562
11598
  cmd.command("create").description("Create a new document").requiredOption("--title <title>", "Document title").option("--body <markdown>", "Document body (markdown)").addOption(new Option("--body-file <path>", "Read body from file").conflicts("body")).option("--json", "Output as JSON").action(async (opts) => {
11599
+ const body = readBody(opts);
11563
11600
  const cfg = requireConfig5();
11564
11601
  const client = createTypedClient(cfg);
11565
11602
  const ksId = await getKnowledgeStoreId(client, cfg.active_account.target.space_id);
11566
- const body = readBody(opts);
11567
11603
  const result = await client.page.create.mutate({
11568
11604
  knowledge_store_id: ksId,
11569
11605
  title: opts.title,
@@ -11577,12 +11613,12 @@ ${page.body}`);
11577
11613
  });
11578
11614
  cmd.command("update").description("Update a document").argument("<id>", "Page ID").option("--title <title>", "New title").option("--body <markdown>", "New body (markdown)").addOption(new Option("--body-file <path>", "Read body from file").conflicts("body")).option("--json", "Output as JSON").action(async (id, opts) => {
11579
11615
  if (opts.title === undefined && opts.body === undefined && opts.bodyFile === undefined) {
11580
- throw new Error("Specify at least one of --title, --body, or --body-file.");
11616
+ throw new CliUsageError("Specify at least one of --title, --body, or --body-file.");
11581
11617
  }
11618
+ const body = readBody(opts);
11582
11619
  const cfg = requireConfig5();
11583
11620
  const client = createTypedClient(cfg);
11584
11621
  const ksId = await getKnowledgeStoreId(client, cfg.active_account.target.space_id);
11585
- const body = readBody(opts);
11586
11622
  await client.page.update.mutate({
11587
11623
  id,
11588
11624
  knowledge_store_id: ksId,
@@ -11807,6 +11843,7 @@ var init_docs = __esm(() => {
11807
11843
  init_dist8();
11808
11844
  init_dist();
11809
11845
  init_commander();
11846
+ init_errors();
11810
11847
  init_client();
11811
11848
  init_trpc();
11812
11849
  init_logger();
@@ -11958,25 +11995,218 @@ var init_integrations = __esm(() => {
11958
11995
  };
11959
11996
  });
11960
11997
 
11998
+ // src/sessions/branch.ts
11999
+ function recordedBranch(value) {
12000
+ if (typeof value !== "string")
12001
+ return null;
12002
+ const branch = value.trim();
12003
+ return branch && branch !== "HEAD" ? branch : null;
12004
+ }
12005
+ function branchFromClaudeTranscript(text) {
12006
+ let last = null;
12007
+ for (const match of text.matchAll(/"gitBranch":\s*("(?:[^"\\]|\\.)*")/g)) {
12008
+ try {
12009
+ last = recordedBranch(JSON.parse(match[1])) ?? last;
12010
+ } catch {}
12011
+ }
12012
+ return last;
12013
+ }
12014
+ function branchFromCodexTranscript(text) {
12015
+ for (const line of text.split(`
12016
+ `, CODEX_META_LINES)) {
12017
+ if (!line.includes('"session_meta"'))
12018
+ continue;
12019
+ try {
12020
+ const record = JSON.parse(line);
12021
+ if (record.type === "session_meta")
12022
+ return recordedBranch(record.payload?.git?.branch);
12023
+ } catch {}
12024
+ }
12025
+ return null;
12026
+ }
12027
+ function parseReflog(out) {
12028
+ const entries = [];
12029
+ for (const line of out.split(`
12030
+ `)) {
12031
+ const match = /^HEAD@\{(\d+)\}\t(.*)$/.exec(line);
12032
+ if (match)
12033
+ entries.push({ at: Number(match[1]), subject: match[2] });
12034
+ }
12035
+ return entries;
12036
+ }
12037
+ function checkoutBranch(name) {
12038
+ return /^[0-9a-f]{7,40}$/.test(name) ? null : recordedBranch(name);
12039
+ }
12040
+ function branchFromReflog(entries, endSec, currentBranch) {
12041
+ if (entries.length === 0)
12042
+ return null;
12043
+ let oldest = Number.POSITIVE_INFINITY;
12044
+ let before = null;
12045
+ let after = null;
12046
+ for (const entry of entries) {
12047
+ oldest = Math.min(oldest, entry.at);
12048
+ const match = CHECKOUT.exec(entry.subject);
12049
+ if (!match)
12050
+ continue;
12051
+ if (entry.at <= endSec) {
12052
+ if (!before || entry.at > before.at)
12053
+ before = { at: entry.at, to: match[2] };
12054
+ } else if (!after || entry.at <= after.at) {
12055
+ after = { at: entry.at, from: match[1] };
12056
+ }
12057
+ }
12058
+ if (endSec < oldest)
12059
+ return null;
12060
+ if (before)
12061
+ return checkoutBranch(before.to);
12062
+ if (after)
12063
+ return checkoutBranch(after.from);
12064
+ return currentBranch();
12065
+ }
12066
+ var CODEX_META_LINES = 50, CHECKOUT;
12067
+ var init_branch = __esm(() => {
12068
+ CHECKOUT = /^checkout: moving from (\S+) to (\S+)$/;
12069
+ });
12070
+
12071
+ // src/sessions/capture.ts
12072
+ import { existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync11, renameSync as renameSync3, writeFileSync as writeFileSync7 } from "node:fs";
12073
+ import { basename as basename2, join as join10 } from "node:path";
12074
+ function capturePath(configDir, key) {
12075
+ const [harness, id, ...rest] = key.split("/");
12076
+ if (rest.length > 0 || !SAFE_SEGMENT.test(harness ?? "") || !SAFE_SEGMENT.test(id ?? "")) {
12077
+ return null;
12078
+ }
12079
+ return join10(configDir, CAPTURE_DIRNAME, harness, `${id}.json`);
12080
+ }
12081
+ function readCapturedSession(key, configDir = getConfigDir()) {
12082
+ const path = capturePath(configDir, key);
12083
+ if (!path)
12084
+ return null;
12085
+ try {
12086
+ const raw = JSON.parse(readFileSync11(path, "utf-8"));
12087
+ return {
12088
+ ...typeof raw.dir === "string" ? { dir: raw.dir } : {},
12089
+ ...typeof raw.branch === "string" ? { branch: raw.branch } : {},
12090
+ at: typeof raw.at === "string" ? raw.at : ""
12091
+ };
12092
+ } catch {
12093
+ return null;
12094
+ }
12095
+ }
12096
+ function recordCapturedSession(key, update, configDir = getConfigDir(), now = new Date) {
12097
+ const path = capturePath(configDir, key);
12098
+ if (!path)
12099
+ return false;
12100
+ const previous = readCapturedSession(key, configDir);
12101
+ const dir = update.dir ?? previous?.dir;
12102
+ const branch = update.branch ?? previous?.branch;
12103
+ const record = {
12104
+ ...dir ? { dir } : {},
12105
+ ...branch ? { branch } : {},
12106
+ at: now.toISOString()
12107
+ };
12108
+ try {
12109
+ const parent = join10(path, "..");
12110
+ if (!existsSync11(parent))
12111
+ mkdirSync7(parent, { recursive: true, mode: 448 });
12112
+ const tmp = `${path}.${process.pid}.tmp`;
12113
+ writeFileSync7(tmp, JSON.stringify(record), { mode: 384 });
12114
+ renameSync3(tmp, path);
12115
+ return true;
12116
+ } catch (err) {
12117
+ logger.debug("sync", `could not record ${key}: ${err.message}`);
12118
+ return false;
12119
+ }
12120
+ }
12121
+ function captureCursorStop(payload, deps = {}) {
12122
+ if (typeof payload !== "object" || payload === null)
12123
+ return false;
12124
+ const hook = payload;
12125
+ if (hook.cursor_version === undefined)
12126
+ return false;
12127
+ const id = typeof hook.transcript_path === "string" && hook.transcript_path.endsWith(".jsonl") ? basename2(hook.transcript_path, ".jsonl") : hook.conversation_id;
12128
+ if (typeof id !== "string")
12129
+ return false;
12130
+ const roots = hook.workspace_roots;
12131
+ const dir = Array.isArray(roots) && typeof roots[0] === "string" ? roots[0] : undefined;
12132
+ if (!dir?.startsWith("/"))
12133
+ return false;
12134
+ const branch = (deps.currentBranch ?? currentBranchOfDir)(dir);
12135
+ return recordCapturedSession(`cursor/${id}`, { dir, branch }, deps.configDir, deps.now);
12136
+ }
12137
+ function readHookStdin(stream = process.stdin, timeoutMs = HOOK_STDIN_TIMEOUT_MS, maxBytes = HOOK_STDIN_MAX_BYTES) {
12138
+ if (stream.isTTY)
12139
+ return Promise.resolve(null);
12140
+ return new Promise((resolve) => {
12141
+ const chunks = [];
12142
+ let size = 0;
12143
+ let done = false;
12144
+ let timer;
12145
+ const finish = (value) => {
12146
+ if (done)
12147
+ return;
12148
+ done = true;
12149
+ clearTimeout(timer);
12150
+ stream.removeAllListeners("data");
12151
+ stream.pause();
12152
+ stream.destroy?.();
12153
+ resolve(value);
12154
+ };
12155
+ stream.on("data", (chunk) => {
12156
+ const buf = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
12157
+ size += buf.length;
12158
+ if (size > maxBytes)
12159
+ return finish(null);
12160
+ chunks.push(buf);
12161
+ });
12162
+ stream.on("end", () => {
12163
+ try {
12164
+ finish(JSON.parse(Buffer.concat(chunks).toString("utf-8")));
12165
+ } catch {
12166
+ finish(null);
12167
+ }
12168
+ });
12169
+ stream.on("error", () => finish(null));
12170
+ timer = setTimeout(() => finish(null), timeoutMs);
12171
+ });
12172
+ }
12173
+ async function captureHookSession(stream) {
12174
+ try {
12175
+ const payload = await readHookStdin(stream);
12176
+ if (payload !== null)
12177
+ captureCursorStop(payload);
12178
+ } catch (err) {
12179
+ logger.debug("sync", `hook capture failed: ${err instanceof Error ? err.message : err}`);
12180
+ }
12181
+ }
12182
+ var CAPTURE_DIRNAME = "session-captures", HOOK_STDIN_TIMEOUT_MS = 500, HOOK_STDIN_MAX_BYTES, SAFE_SEGMENT;
12183
+ var init_capture = __esm(() => {
12184
+ init_config();
12185
+ init_logger();
12186
+ init_repo();
12187
+ HOOK_STDIN_MAX_BYTES = 1024 * 1024;
12188
+ SAFE_SEGMENT = /^[A-Za-z0-9_-]+$/;
12189
+ });
12190
+
11961
12191
  // src/sessions/project-dir.ts
11962
12192
  import {
11963
12193
  closeSync as closeSync4,
11964
- existsSync as existsSync11,
11965
- mkdirSync as mkdirSync7,
12194
+ existsSync as existsSync12,
12195
+ mkdirSync as mkdirSync8,
11966
12196
  openSync as openSync4,
11967
- readFileSync as readFileSync11,
12197
+ readFileSync as readFileSync12,
11968
12198
  readSync as readSync3,
11969
- renameSync as renameSync3,
12199
+ renameSync as renameSync4,
11970
12200
  statSync as statSync4,
11971
- writeFileSync as writeFileSync7
12201
+ writeFileSync as writeFileSync8
11972
12202
  } from "node:fs";
11973
- import { join as join10 } from "node:path";
12203
+ import { join as join11 } from "node:path";
11974
12204
  function cachePath(configDir) {
11975
- return join10(configDir, CACHE_FILENAME2);
12205
+ return join11(configDir, CACHE_FILENAME2);
11976
12206
  }
11977
12207
  function loadCacheFile(configDir) {
11978
12208
  try {
11979
- const raw = JSON.parse(readFileSync11(cachePath(configDir), "utf-8"));
12209
+ const raw = JSON.parse(readFileSync12(cachePath(configDir), "utf-8"));
11980
12210
  if (raw.schema_version !== CACHE_SCHEMA_VERSION || typeof raw.entries !== "object")
11981
12211
  return {};
11982
12212
  return raw.entries;
@@ -11986,13 +12216,13 @@ function loadCacheFile(configDir) {
11986
12216
  }
11987
12217
  function saveCacheFile(configDir, entries) {
11988
12218
  try {
11989
- if (!existsSync11(configDir))
11990
- mkdirSync7(configDir, { recursive: true, mode: 448 });
12219
+ if (!existsSync12(configDir))
12220
+ mkdirSync8(configDir, { recursive: true, mode: 448 });
11991
12221
  const path = cachePath(configDir);
11992
12222
  const tmp = `${path}.${process.pid}.tmp`;
11993
12223
  const file = { schema_version: CACHE_SCHEMA_VERSION, entries };
11994
- writeFileSync7(tmp, JSON.stringify(file), { mode: 384 });
11995
- renameSync3(tmp, path);
12224
+ writeFileSync8(tmp, JSON.stringify(file), { mode: 384 });
12225
+ renameSync4(tmp, path);
11996
12226
  } catch {}
11997
12227
  }
11998
12228
  function readHead(path, bytes = HEAD_BYTES) {
@@ -12026,7 +12256,7 @@ function cwdFromJsonlHead(text) {
12026
12256
  }
12027
12257
  return null;
12028
12258
  }
12029
- function unmungeSlug(slug, exists = existsSync11) {
12259
+ function unmungeSlug(slug, exists = existsSync12) {
12030
12260
  const tokens = slug.replace(/^-/, "").split("-");
12031
12261
  if (tokens.length === 0 || tokens[0] === "")
12032
12262
  return null;
@@ -12043,6 +12273,13 @@ function unmungeSlug(slug, exists = existsSync11) {
12043
12273
  };
12044
12274
  return walk("", 0);
12045
12275
  }
12276
+ function readWholeFile(path) {
12277
+ try {
12278
+ return readFileSync12(path, "utf-8");
12279
+ } catch {
12280
+ return null;
12281
+ }
12282
+ }
12046
12283
  function fileMtime(path) {
12047
12284
  try {
12048
12285
  return statSync4(path).mtime.toISOString();
@@ -12051,9 +12288,10 @@ function fileMtime(path) {
12051
12288
  }
12052
12289
  }
12053
12290
  function createProjectDirResolver(configDir = getConfigDir(), deps = {}) {
12054
- const exists = deps.exists ?? existsSync11;
12291
+ const exists = deps.exists ?? existsSync12;
12055
12292
  const head = deps.readHead ?? readHead;
12056
12293
  const mtime = deps.mtime ?? fileMtime;
12294
+ const captured = deps.captured ?? ((key) => readCapturedSession(key, configDir));
12057
12295
  const entries = loadCacheFile(configDir);
12058
12296
  let dirty = false;
12059
12297
  const compute = (session) => {
@@ -12071,14 +12309,47 @@ function createProjectDirResolver(configDir = getConfigDir(), deps = {}) {
12071
12309
  const text = head(session.path);
12072
12310
  return text ? cwdFromJsonlHead(text) : null;
12073
12311
  }
12074
- case "cursor":
12312
+ case "cursor": {
12313
+ const hookDir = captured(`cursor/${session.id}`)?.dir;
12314
+ if (hookDir)
12315
+ return hookDir;
12075
12316
  return session.project ? unmungeSlug(session.project, exists) : null;
12317
+ }
12076
12318
  default:
12077
12319
  return null;
12078
12320
  }
12079
12321
  };
12080
12322
  const repoOfDir = deps.repoOfDir ?? originRepoOfDir;
12081
12323
  const repoByDir = new Map;
12324
+ const readTranscript = deps.readTranscript ?? readWholeFile;
12325
+ const reflogOfDir = deps.reflogOfDir ?? headReflogOfDir;
12326
+ const currentBranch = deps.currentBranch ?? currentBranchOfDir;
12327
+ const reflogByDir = new Map;
12328
+ const currentByDir = new Map;
12329
+ const transcriptBranch = (session) => {
12330
+ if (session.harness !== "claude" && session.harness !== "codex")
12331
+ return null;
12332
+ const text = readTranscript(session.path);
12333
+ if (text === null)
12334
+ return null;
12335
+ return session.harness === "claude" ? branchFromClaudeTranscript(text) : branchFromCodexTranscript(text);
12336
+ };
12337
+ const reflogBranch = (session) => {
12338
+ const dir = resolve(session);
12339
+ const end = Date.parse(session.updated);
12340
+ if (dir === null || Number.isNaN(end))
12341
+ return null;
12342
+ let entries = reflogByDir.get(dir);
12343
+ if (!entries) {
12344
+ entries = parseReflog(reflogOfDir(dir) ?? "");
12345
+ reflogByDir.set(dir, entries);
12346
+ }
12347
+ return branchFromReflog(entries, Math.floor(end / 1000), () => {
12348
+ if (!currentByDir.has(dir))
12349
+ currentByDir.set(dir, currentBranch(dir));
12350
+ return currentByDir.get(dir) ?? null;
12351
+ });
12352
+ };
12082
12353
  const resolve = (session) => {
12083
12354
  const key = `${session.harness}/${session.id}`;
12084
12355
  const cached = entries[key];
@@ -12111,6 +12382,9 @@ function createProjectDirResolver(configDir = getConfigDir(), deps = {}) {
12111
12382
  dirty = true;
12112
12383
  return repo;
12113
12384
  },
12385
+ resolveBranch(session) {
12386
+ return transcriptBranch(session) ?? captured(`${session.harness}/${session.id}`)?.branch ?? reflogBranch(session);
12387
+ },
12114
12388
  flush() {
12115
12389
  if (!dirty)
12116
12390
  return;
@@ -12122,6 +12396,8 @@ function createProjectDirResolver(configDir = getConfigDir(), deps = {}) {
12122
12396
  var CACHE_FILENAME2 = "project-dirs.json", CACHE_SCHEMA_VERSION = 1, HEAD_BYTES, HEAD_LINES = 50;
12123
12397
  var init_project_dir = __esm(() => {
12124
12398
  init_config();
12399
+ init_branch();
12400
+ init_capture();
12125
12401
  init_repo();
12126
12402
  HEAD_BYTES = 128 * 1024;
12127
12403
  });
@@ -12863,7 +13139,7 @@ var init_queries = __esm(() => {
12863
13139
  });
12864
13140
 
12865
13141
  // src/report/digest.ts
12866
- import { readFileSync as readFileSync12 } from "node:fs";
13142
+ import { readFileSync as readFileSync13 } from "node:fs";
12867
13143
  function asRecord2(value) {
12868
13144
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
12869
13145
  }
@@ -13094,11 +13370,11 @@ function sessionToDigest(session) {
13094
13370
  try {
13095
13371
  switch (session.harness) {
13096
13372
  case "claude":
13097
- return { turns: digestClaude(readFileSync12(session.path, "utf8")) };
13373
+ return { turns: digestClaude(readFileSync13(session.path, "utf8")) };
13098
13374
  case "cursor":
13099
- return { turns: digestCursor(readFileSync12(session.path, "utf8")) };
13375
+ return { turns: digestCursor(readFileSync13(session.path, "utf8")) };
13100
13376
  case "codex":
13101
- return { turns: digestCodex(readFileSync12(session.path, "utf8")) };
13377
+ return { turns: digestCodex(readFileSync13(session.path, "utf8")) };
13102
13378
  case "opencode": {
13103
13379
  const turns = readSessionTurns(session).map((turn, index) => ({
13104
13380
  role: turn.role,
@@ -13319,17 +13595,17 @@ var init_notes = __esm(() => {
13319
13595
  });
13320
13596
 
13321
13597
  // src/report/write.ts
13322
- import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "node:fs";
13598
+ import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "node:fs";
13323
13599
  import { tmpdir } from "node:os";
13324
- import { dirname as dirname4, join as join11, resolve } from "node:path";
13600
+ import { dirname as dirname4, join as join12, resolve as resolve2 } from "node:path";
13325
13601
  import { pathToFileURL } from "node:url";
13326
13602
  function defaultReportPath() {
13327
- return join11(tmpdir(), "dosu-knowledge-report.html");
13603
+ return join12(tmpdir(), "dosu-knowledge-report.html");
13328
13604
  }
13329
13605
  async function writeAndOpenReport(options) {
13330
- const out = resolve(options.out ?? defaultReportPath());
13331
- mkdirSync8(dirname4(out), { recursive: true });
13332
- writeFileSync8(out, options.html, "utf8");
13606
+ const out = resolve2(options.out ?? defaultReportPath());
13607
+ mkdirSync9(dirname4(out), { recursive: true });
13608
+ writeFileSync9(out, options.html, "utf8");
13333
13609
  if (options.open !== false) {
13334
13610
  const url = pathToFileURL(out).href;
13335
13611
  if (options.openUrl) {
@@ -13344,7 +13620,7 @@ async function writeAndOpenReport(options) {
13344
13620
  var init_write = () => {};
13345
13621
 
13346
13622
  // src/report/generate.ts
13347
- import { basename as basename2 } from "node:path";
13623
+ import { basename as basename3 } from "node:path";
13348
13624
  function sessionsForNotes(notes, sessions) {
13349
13625
  const ids = new Set(notes.map((n) => n.transcript_id).filter((id) => Boolean(id)));
13350
13626
  return sessions.filter((s) => ids.has(s.id));
@@ -13353,7 +13629,7 @@ function defaultProjectName() {
13353
13629
  const resolver = createProjectDirResolver();
13354
13630
  return (session) => {
13355
13631
  const dir = resolver.resolve(session);
13356
- return dir ? basename2(dir) : null;
13632
+ return dir ? basename3(dir) : null;
13357
13633
  };
13358
13634
  }
13359
13635
  function noteTime(note) {
@@ -13426,8 +13702,8 @@ var init_backlog = __esm(() => {
13426
13702
  });
13427
13703
 
13428
13704
  // src/sync/lock.ts
13429
- import { existsSync as existsSync12, readFileSync as readFileSync13, rmSync as rmSync2, statSync as statSync5, writeFileSync as writeFileSync9 } from "node:fs";
13430
- import { join as join12 } from "node:path";
13705
+ import { existsSync as existsSync13, readFileSync as readFileSync14, rmSync as rmSync2, statSync as statSync5, writeFileSync as writeFileSync10 } from "node:fs";
13706
+ import { join as join13 } from "node:path";
13431
13707
  function processAlive(pid) {
13432
13708
  try {
13433
13709
  process.kill(pid, 0);
@@ -13437,7 +13713,7 @@ function processAlive(pid) {
13437
13713
  }
13438
13714
  }
13439
13715
  function lockPath(configDir = getConfigDir()) {
13440
- return join12(configDir, LOCK_FILENAME);
13716
+ return join13(configDir, LOCK_FILENAME);
13441
13717
  }
13442
13718
  function stopSyncRun(pid, configDir = getConfigDir(), kill = process.kill.bind(process)) {
13443
13719
  if (!Number.isInteger(pid) || pid <= 0)
@@ -13454,7 +13730,7 @@ function stopSyncRun(pid, configDir = getConfigDir(), kill = process.kill.bind(p
13454
13730
  }
13455
13731
  try {
13456
13732
  const path = lockPath(configDir);
13457
- if (existsSync12(path) && readFileSync13(path, "utf8") === String(pid)) {
13733
+ if (existsSync13(path) && readFileSync14(path, "utf8") === String(pid)) {
13458
13734
  rmSync2(path, { force: true });
13459
13735
  }
13460
13736
  } catch {}
@@ -13465,7 +13741,7 @@ function fileLock(configDir = getConfigDir(), now = () => new Date) {
13465
13741
  let held = false;
13466
13742
  const tryCreate = () => {
13467
13743
  try {
13468
- writeFileSync9(path, String(process.pid), { flag: "wx" });
13744
+ writeFileSync10(path, String(process.pid), { flag: "wx" });
13469
13745
  return true;
13470
13746
  } catch {
13471
13747
  return false;
@@ -13479,7 +13755,7 @@ function fileLock(configDir = getConfigDir(), now = () => new Date) {
13479
13755
  }
13480
13756
  try {
13481
13757
  const age = now().getTime() - statSync5(path).mtimeMs;
13482
- const holder = Number.parseInt(readFileSync13(path, "utf8"), 10);
13758
+ const holder = Number.parseInt(readFileSync14(path, "utf8"), 10);
13483
13759
  const holderDead = Number.isInteger(holder) && holder > 0 && !processAlive(holder);
13484
13760
  if (age > STALE_LOCK_MS || holderDead) {
13485
13761
  rmSync2(path, { force: true });
@@ -13494,7 +13770,7 @@ function fileLock(configDir = getConfigDir(), now = () => new Date) {
13494
13770
  return;
13495
13771
  held = false;
13496
13772
  try {
13497
- if (existsSync12(path) && readFileSync13(path, "utf8") === String(process.pid)) {
13773
+ if (existsSync13(path) && readFileSync14(path, "utf8") === String(process.pid)) {
13498
13774
  rmSync2(path, { force: true });
13499
13775
  }
13500
13776
  } catch {}
@@ -13508,7 +13784,7 @@ var init_lock = __esm(() => {
13508
13784
  });
13509
13785
 
13510
13786
  // src/sync/status.ts
13511
- import { readFileSync as readFileSync14, statSync as statSync6 } from "node:fs";
13787
+ import { readFileSync as readFileSync15, statSync as statSync6 } from "node:fs";
13512
13788
  function formatTokenCount(tokens) {
13513
13789
  if (tokens < 1000)
13514
13790
  return String(tokens);
@@ -13531,7 +13807,7 @@ function defaultIsProcessAlive2(pid) {
13531
13807
  }
13532
13808
  function defaultReadLog() {
13533
13809
  try {
13534
- return readFileSync14(logger.getLogPath(), "utf-8");
13810
+ return readFileSync15(logger.getLogPath(), "utf-8");
13535
13811
  } catch {
13536
13812
  return "";
13537
13813
  }
@@ -13539,7 +13815,7 @@ function defaultReadLog() {
13539
13815
  function readLockFile(configDir) {
13540
13816
  const path = lockPath(configDir);
13541
13817
  try {
13542
- const pid = Number.parseInt(readFileSync14(path, "utf-8"), 10);
13818
+ const pid = Number.parseInt(readFileSync15(path, "utf-8"), 10);
13543
13819
  return { pid: Number.isNaN(pid) ? -1 : pid, mtime: statSync6(path).mtime };
13544
13820
  } catch {
13545
13821
  return null;
@@ -13631,6 +13907,7 @@ async function runKnowledgeSync(options = {}) {
13631
13907
  }
13632
13908
  let ready;
13633
13909
  let open;
13910
+ let branchOf;
13634
13911
  try {
13635
13912
  const listSessions = deps.listSessions ?? (() => options.bootstrap ? scanAgentSessions({}) : scanAgentSessions({
13636
13913
  since: new Date(now().getTime() - GATE_WINDOW_DAYS * 24 * 60 * 60 * 1000),
@@ -13639,11 +13916,14 @@ async function runKnowledgeSync(options = {}) {
13639
13916
  const scanned = await listSessions();
13640
13917
  let flush;
13641
13918
  let locator = deps.locator;
13642
- if (!locator) {
13919
+ let resolveBranch = deps.resolveBranch;
13920
+ if (!locator || !resolveBranch) {
13643
13921
  const resolver = createProjectDirResolver();
13644
- locator = resolver;
13922
+ locator ??= resolver;
13923
+ resolveBranch ??= resolver.resolveBranch;
13645
13924
  flush = resolver.flush;
13646
13925
  }
13926
+ branchOf = resolveBranch;
13647
13927
  const repoFilter = studyRepoFilter(state, () => scanAgentSessions({}), locator);
13648
13928
  if (state.project_filter) {
13649
13929
  delete state.project_filter;
@@ -13712,10 +13992,11 @@ async function runKnowledgeSync(options = {}) {
13712
13992
  } else if (isIncognito(candidate)) {
13713
13993
  incognito += 1;
13714
13994
  logger.debug("sync", `skipping incognito session ${candidate.harness}/${candidate.id}`);
13715
- } else if (worthStudying(candidate)) {
13716
- batch.push(candidate);
13717
- } else {
13995
+ } else if (!worthStudying(candidate)) {
13718
13996
  trivial += 1;
13997
+ } else {
13998
+ const branch = candidate.repo ? branchOf(candidate) : null;
13999
+ batch.push(branch ? { ...candidate, branch } : candidate);
13719
14000
  }
13720
14001
  }
13721
14002
  const skippedNote = `${trivial} trivial, ${incognito} incognito${alreadyStudied > 0 ? `, ${alreadyStudied} already studied` : ""} skipped`;
@@ -13843,7 +14124,7 @@ var init_sync = __esm(() => {
13843
14124
  });
13844
14125
 
13845
14126
  // src/learner/conflicts.ts
13846
- import { existsSync as existsSync13, readFileSync as readFileSync15 } from "node:fs";
14127
+ import { existsSync as existsSync14, readFileSync as readFileSync16 } from "node:fs";
13847
14128
  function managedSettingsPaths(platform = process.platform) {
13848
14129
  switch (platform) {
13849
14130
  case "darwin":
@@ -13872,11 +14153,11 @@ function conflictingKeysIn(settings) {
13872
14153
  function detectSettingsConflicts(paths = managedSettingsPaths()) {
13873
14154
  const conflicts = [];
13874
14155
  for (const file of paths) {
13875
- if (!existsSync13(file))
14156
+ if (!existsSync14(file))
13876
14157
  continue;
13877
14158
  let settings;
13878
14159
  try {
13879
- settings = JSON.parse(readFileSync15(file, "utf8"));
14160
+ settings = JSON.parse(readFileSync16(file, "utf8"));
13880
14161
  } catch {
13881
14162
  conflicts.push({ file, keys: [UNREADABLE_SETTINGS_KEY] });
13882
14163
  continue;
@@ -13901,14 +14182,14 @@ var init_conflicts = __esm(() => {
13901
14182
  });
13902
14183
 
13903
14184
  // src/telemetry/debug-id.ts
13904
- var BUNDLE_DEBUG_ID_PLACEHOLDER = "01f74cf6-cdbb-b296-6475-6e2164756e21";
14185
+ var BUNDLE_DEBUG_ID_PLACEHOLDER = "49497211-cd7a-a697-6475-6e2164756e21";
13905
14186
 
13906
14187
  // src/telemetry/telemetry.ts
13907
14188
  import { randomUUID as randomUUID2 } from "node:crypto";
13908
- import { existsSync as existsSync14 } from "node:fs";
14189
+ import { existsSync as existsSync15 } from "node:fs";
13909
14190
  import { request as httpRequest2 } from "node:http";
13910
14191
  import { request as httpsRequest } from "node:https";
13911
- import { isAbsolute, relative, resolve as resolve2, sep } from "node:path";
14192
+ import { isAbsolute, relative, resolve as resolve3, sep } from "node:path";
13912
14193
  import { fileURLToPath as fileURLToPath2 } from "node:url";
13913
14194
  function safeString(value, pattern, fallback) {
13914
14195
  if (typeof value !== "string" || !pattern.test(value))
@@ -14033,7 +14314,7 @@ function parseOwnedStackLine(originalLine, packageRoot) {
14033
14314
  }
14034
14315
  if (!isAbsolute(absolutePath))
14035
14316
  return;
14036
- const resolvedPath = resolve2(absolutePath);
14317
+ const resolvedPath = resolve3(absolutePath);
14037
14318
  const relativePath = relative(packageRoot, resolvedPath);
14038
14319
  if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep}`) || isAbsolute(relativePath)) {
14039
14320
  return;
@@ -14043,7 +14324,7 @@ function parseOwnedStackLine(originalLine, packageRoot) {
14043
14324
  return;
14044
14325
  }
14045
14326
  try {
14046
- if (!existsSync14(resolvedPath))
14327
+ if (!existsSync15(resolvedPath))
14047
14328
  return;
14048
14329
  } catch {
14049
14330
  return;
@@ -14926,9 +15207,9 @@ var init_agent_select = __esm(() => {
14926
15207
  });
14927
15208
 
14928
15209
  // src/incognito/agents.ts
14929
- import { existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync16, unlinkSync as unlinkSync2, writeFileSync as writeFileSync10 } from "node:fs";
15210
+ import { existsSync as existsSync16, mkdirSync as mkdirSync10, readFileSync as readFileSync17, unlinkSync as unlinkSync2, writeFileSync as writeFileSync11 } from "node:fs";
14930
15211
  import { homedir as homedir4 } from "node:os";
14931
- import { dirname as dirname5, join as join13 } from "node:path";
15212
+ import { dirname as dirname5, join as join14 } from "node:path";
14932
15213
  function withFrontmatter(body) {
14933
15214
  return `---
14934
15215
  description: ${DESCRIPTION}
@@ -14937,10 +15218,10 @@ description: ${DESCRIPTION}
14937
15218
  ${body}`;
14938
15219
  }
14939
15220
  function claudeConfigDir2() {
14940
- return process.env.CLAUDE_CONFIG_DIR || join13(homedir4(), ".claude");
15221
+ return process.env.CLAUDE_CONFIG_DIR || join14(homedir4(), ".claude");
14941
15222
  }
14942
15223
  function codexHome2() {
14943
- return process.env.CODEX_HOME || join13(homedir4(), ".codex");
15224
+ return process.env.CODEX_HOME || join14(homedir4(), ".codex");
14944
15225
  }
14945
15226
  function fileAgent(options) {
14946
15227
  const { commandPath, content } = options;
@@ -14951,29 +15232,29 @@ function fileAgent(options) {
14951
15232
  commandPath,
14952
15233
  isEnabled: () => {
14953
15234
  const path = commandPath();
14954
- if (!existsSync15(path))
15235
+ if (!existsSync16(path))
14955
15236
  return false;
14956
15237
  try {
14957
- return readFileSync16(path, "utf-8").includes(INCOGNITO_MARKER);
15238
+ return readFileSync17(path, "utf-8").includes(INCOGNITO_MARKER);
14958
15239
  } catch {
14959
15240
  return false;
14960
15241
  }
14961
15242
  },
14962
15243
  enable: () => {
14963
15244
  const path = commandPath();
14964
- if (existsSync15(path)) {
14965
- if (readFileSync16(path, "utf-8") === content)
15245
+ if (existsSync16(path)) {
15246
+ if (readFileSync17(path, "utf-8") === content)
14966
15247
  return "unchanged";
14967
- writeFileSync10(path, content, "utf-8");
15248
+ writeFileSync11(path, content, "utf-8");
14968
15249
  return "updated";
14969
15250
  }
14970
- mkdirSync9(dirname5(path), { recursive: true });
14971
- writeFileSync10(path, content, "utf-8");
15251
+ mkdirSync10(dirname5(path), { recursive: true });
15252
+ writeFileSync11(path, content, "utf-8");
14972
15253
  return "created";
14973
15254
  },
14974
15255
  disable: () => {
14975
15256
  const path = commandPath();
14976
- if (!existsSync15(path))
15257
+ if (!existsSync16(path))
14977
15258
  return "not_found";
14978
15259
  unlinkSync2(path);
14979
15260
  return "removed";
@@ -14986,21 +15267,21 @@ function allIncognitoAgents() {
14986
15267
  id: "claude",
14987
15268
  name: "Claude Code",
14988
15269
  detectPath: claudeConfigDir2,
14989
- commandPath: () => join13(claudeConfigDir2(), "commands", FILE_NAME),
15270
+ commandPath: () => join14(claudeConfigDir2(), "commands", FILE_NAME),
14990
15271
  content: withFrontmatter(INCOGNITO_COMMAND_BODY)
14991
15272
  }),
14992
15273
  fileAgent({
14993
15274
  id: "cursor",
14994
15275
  name: "Cursor",
14995
- detectPath: () => join13(homedir4(), ".cursor"),
14996
- commandPath: () => join13(homedir4(), ".cursor", "commands", FILE_NAME),
15276
+ detectPath: () => join14(homedir4(), ".cursor"),
15277
+ commandPath: () => join14(homedir4(), ".cursor", "commands", FILE_NAME),
14997
15278
  content: INCOGNITO_COMMAND_BODY
14998
15279
  }),
14999
15280
  fileAgent({
15000
15281
  id: "codex",
15001
15282
  name: "Codex",
15002
15283
  detectPath: codexHome2,
15003
- commandPath: () => join13(codexHome2(), "prompts", FILE_NAME),
15284
+ commandPath: () => join14(codexHome2(), "prompts", FILE_NAME),
15004
15285
  content: withFrontmatter(INCOGNITO_COMMAND_BODY)
15005
15286
  })
15006
15287
  ];
@@ -15084,7 +15365,7 @@ var init_knowledge_incognito = __esm(() => {
15084
15365
 
15085
15366
  // src/statusline/agents.ts
15086
15367
  import { homedir as homedir5 } from "node:os";
15087
- import { join as join14 } from "node:path";
15368
+ import { join as join15 } from "node:path";
15088
15369
  function statuslineCommand(agentId) {
15089
15370
  if (process.env.DOSU_DEV !== "true")
15090
15371
  return `dosu ${RENDER_ARGS} ${agentId}`;
@@ -15094,7 +15375,7 @@ function isDosuStatuslineCommand(command) {
15094
15375
  return typeof command === "string" && command.includes(RENDER_ARGS);
15095
15376
  }
15096
15377
  function claudeConfigDir3() {
15097
- return process.env.CLAUDE_CONFIG_DIR || join14(homedir5(), ".claude");
15378
+ return process.env.CLAUDE_CONFIG_DIR || join15(homedir5(), ".claude");
15098
15379
  }
15099
15380
  function statuslineOf(config) {
15100
15381
  const value = config.statusLine;
@@ -15135,7 +15416,7 @@ function allStatuslineAgents() {
15135
15416
  id: "claude",
15136
15417
  name: "Claude Code",
15137
15418
  detectPath: claudeConfigDir3,
15138
- configPath: () => join14(claudeConfigDir3(), "settings.json")
15419
+ configPath: () => join15(claudeConfigDir3(), "settings.json")
15139
15420
  }),
15140
15421
  configAgent({
15141
15422
  id: "cursor",
@@ -15400,12 +15681,12 @@ var init_backfill_run = __esm(() => {
15400
15681
  });
15401
15682
 
15402
15683
  // src/learner/config-dir.ts
15403
- import { mkdtempSync, rmSync as rmSync3, writeFileSync as writeFileSync11 } from "node:fs";
15684
+ import { mkdtempSync, rmSync as rmSync3, writeFileSync as writeFileSync12 } from "node:fs";
15404
15685
  import { tmpdir as tmpdir2 } from "node:os";
15405
- import { join as join15 } from "node:path";
15686
+ import { join as join16 } from "node:path";
15406
15687
  function createRunConfigDir() {
15407
- const path = mkdtempSync(join15(tmpdir2(), "dosu-learner-"));
15408
- writeFileSync11(join15(path, ".claude.json"), JSON.stringify({ hasCompletedOnboarding: true }));
15688
+ const path = mkdtempSync(join16(tmpdir2(), "dosu-learner-"));
15689
+ writeFileSync12(join16(path, ".claude.json"), JSON.stringify({ hasCompletedOnboarding: true }));
15409
15690
  return {
15410
15691
  path,
15411
15692
  cleanup() {
@@ -15453,10 +15734,10 @@ var init_env = __esm(() => {
15453
15734
  });
15454
15735
 
15455
15736
  // src/learner/executable.ts
15456
- import { accessSync, constants as constants2, existsSync as existsSync16 } from "node:fs";
15737
+ import { accessSync, constants as constants2, existsSync as existsSync17 } from "node:fs";
15457
15738
  import { createRequire as createRequire3 } from "node:module";
15458
15739
  import { homedir as homedir6 } from "node:os";
15459
- import { delimiter as delimiter2, dirname as dirname6, join as join16 } from "node:path";
15740
+ import { delimiter as delimiter2, dirname as dirname6, join as join17 } from "node:path";
15460
15741
  function binaryNames(platform = process.platform) {
15461
15742
  return platform === "win32" ? ["claude.exe", "claude.cmd"] : ["claude"];
15462
15743
  }
@@ -15465,7 +15746,7 @@ function sdkNativeBinaryExists() {
15465
15746
  const requireRuntime = createRequire3(import.meta.url);
15466
15747
  const pkg = `@anthropic-ai/claude-agent-sdk-${process.platform}-${process.arch}`;
15467
15748
  const pkgDir = dirname6(requireRuntime.resolve(`${pkg}/package.json`));
15468
- return binaryNames().some((name) => existsSync16(join16(pkgDir, name)));
15749
+ return binaryNames().some((name) => existsSync17(join17(pkgDir, name)));
15469
15750
  } catch {
15470
15751
  return false;
15471
15752
  }
@@ -15481,10 +15762,10 @@ function isExecutable(path) {
15481
15762
  function findSystemClaude(env = process.env, homeDir = homedir6()) {
15482
15763
  const names = binaryNames();
15483
15764
  const dirs = (env.PATH ?? "").split(delimiter2).filter(Boolean);
15484
- dirs.push(join16(homeDir, ".local", "bin"), join16(homeDir, ".claude", "local"));
15765
+ dirs.push(join17(homeDir, ".local", "bin"), join17(homeDir, ".claude", "local"));
15485
15766
  for (const dir of dirs) {
15486
15767
  for (const name of names) {
15487
- const candidate = join16(dir, name);
15768
+ const candidate = join17(dir, name);
15488
15769
  if (isExecutable(candidate))
15489
15770
  return candidate;
15490
15771
  }
@@ -54105,7 +54386,7 @@ var _messageDesc, _zodDesc2, _issuesDesc, _installedToString, initializer = (ins
54105
54386
  });
54106
54387
  }
54107
54388
  }, $ZodError, $ZodRealError;
54108
- var init_errors = __esm(() => {
54389
+ var init_errors2 = __esm(() => {
54109
54390
  init_core();
54110
54391
  init_util();
54111
54392
  _messageDesc = {
@@ -54214,7 +54495,7 @@ var _parse = (_Err) => {
54214
54495
  };
54215
54496
  var init_parse = __esm(() => {
54216
54497
  init_core();
54217
- init_errors();
54498
+ init_errors2();
54218
54499
  init_util();
54219
54500
  safeParse = /* @__PURE__ */ _safeParse($ZodRealError);
54220
54501
  safeParseAsync = /* @__PURE__ */ _safeParseAsync($ZodRealError);
@@ -57216,7 +57497,7 @@ var init_core2 = __esm(() => {
57216
57497
  init_json_schema();
57217
57498
  init_core();
57218
57499
  init_parse();
57219
- init_errors();
57500
+ init_errors2();
57220
57501
  init_schemas();
57221
57502
  init_memoizer();
57222
57503
  init_checks();
@@ -57272,7 +57553,7 @@ var _installedErrorProtos, initializer2 = (inst, issues) => {
57272
57553
  }
57273
57554
  });
57274
57555
  }, ZodRealError;
57275
- var init_errors2 = __esm(() => {
57556
+ var init_errors3 = __esm(() => {
57276
57557
  init_core2();
57277
57558
  init_core2();
57278
57559
  init_util();
@@ -57286,7 +57567,7 @@ var init_errors2 = __esm(() => {
57286
57567
  var parse6, parseAsync2, safeParse2, safeParseAsync2, encode, decode, encodeAsync, decodeAsync, safeEncode, safeDecode, safeEncodeAsync, safeDecodeAsync;
57287
57568
  var init_parse2 = __esm(() => {
57288
57569
  init_core2();
57289
- init_errors2();
57570
+ init_errors3();
57290
57571
  parse6 = /* @__PURE__ */ _parse(ZodRealError);
57291
57572
  parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
57292
57573
  safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
@@ -58035,7 +58316,7 @@ var init_external = __esm(() => {
58035
58316
  init_coerce();
58036
58317
  init_schemas2();
58037
58318
  init_checks2();
58038
- init_errors2();
58319
+ init_errors3();
58039
58320
  init_parse2();
58040
58321
  init_compat();
58041
58322
  });
@@ -58595,6 +58876,7 @@ async function runLearner(options) {
58595
58876
  const readsSinceWrite = new Set;
58596
58877
  const sessionKeys = new Map(options.sessions.map((s) => [s.id, `${s.harness}/${s.id}`]));
58597
58878
  const sessionRepos = new Map(options.sessions.map((s) => [s.id, s.repo]));
58879
+ const sessionBranches = new Map(options.sessions.map((s) => [s.id, s.branch]));
58598
58880
  const notedSessions = new Set;
58599
58881
  const pendingNotes = new Map;
58600
58882
  let turns = 0;
@@ -58673,24 +58955,31 @@ async function runLearner(options) {
58673
58955
  message: "Write each session's notes right after reading THAT session, before reading the next. You have read multiple sessions without writing, so a note cannot be attributed to one. Re-read only the session this note is about, then write it."
58674
58956
  };
58675
58957
  }
58958
+ const noted = currentSession && sessionKeys.get(currentSession);
58959
+ if (!currentSession || !noted) {
58960
+ return {
58961
+ behavior: "deny",
58962
+ message: "Read the session this note is about with read_session first, then write it."
58963
+ };
58964
+ }
58676
58965
  notesWritten += 1;
58677
58966
  readsSinceWrite.clear();
58678
- const noted = currentSession && sessionKeys.get(currentSession);
58679
- if (noted)
58680
- pendingNotes.set(toolUseID, noted);
58967
+ pendingNotes.set(toolUseID, noted);
58681
58968
  const {
58682
58969
  transcript_id: _transcriptByModel,
58683
58970
  repo: _repoByModel,
58684
58971
  branch: _branchByModel,
58685
58972
  ...clean
58686
58973
  } = input;
58687
- const repo = currentSession && sessionRepos.get(currentSession);
58974
+ const repo = sessionRepos.get(currentSession);
58975
+ const branch = repo && sessionBranches.get(currentSession);
58688
58976
  return {
58689
58977
  behavior: "allow",
58690
58978
  updatedInput: {
58691
58979
  ...clean,
58692
- ...currentSession ? { transcript_id: currentSession } : {},
58693
- ...repo ? { repo } : {}
58980
+ transcript_id: currentSession,
58981
+ ...repo ? { repo } : {},
58982
+ ...branch ? { branch } : {}
58694
58983
  }
58695
58984
  };
58696
58985
  }
@@ -58780,8 +59069,8 @@ var init_runner = __esm(() => {
58780
59069
  });
58781
59070
 
58782
59071
  // src/commands/knowledge.ts
58783
- import { existsSync as existsSync18 } from "node:fs";
58784
- import { delimiter as delimiter4, join as join21 } from "node:path";
59072
+ import { existsSync as existsSync19 } from "node:fs";
59073
+ import { delimiter as delimiter4, join as join22 } from "node:path";
58785
59074
  function requireConfig7() {
58786
59075
  const cfg = requireLoginConfig();
58787
59076
  if (!cfg.active_account?.target?.org_id || !cfg.active_account?.target?.space_id) {
@@ -58901,6 +59190,7 @@ ${results.length - opts.limit} more results not shown.`));
58901
59190
  return;
58902
59191
  }
58903
59192
  if (opts.detach) {
59193
+ await captureHookSession();
58904
59194
  const spawned = spawnDetachedSelf([
58905
59195
  "knowledge",
58906
59196
  "sync",
@@ -59205,7 +59495,7 @@ function reportHookFailure(agent, err) {
59205
59495
  }
59206
59496
  function dosuOnPath() {
59207
59497
  const bin = process.platform === "win32" ? "dosu.cmd" : "dosu";
59208
- return (process.env.PATH ?? "").split(delimiter4).some((dir) => dir !== "" && existsSync18(join21(dir, bin)));
59498
+ return (process.env.PATH ?? "").split(delimiter4).some((dir) => dir !== "" && existsSync19(join22(dir, bin)));
59209
59499
  }
59210
59500
  var import_picocolors21;
59211
59501
  var init_knowledge = __esm(() => {
@@ -59215,6 +59505,7 @@ var init_knowledge = __esm(() => {
59215
59505
  init_agents();
59216
59506
  init_formats();
59217
59507
  init_generate();
59508
+ init_capture();
59218
59509
  init_repo();
59219
59510
  init_backlog();
59220
59511
  init_detach();
@@ -59670,7 +59961,7 @@ var init_time_range = __esm(() => {
59670
59961
  });
59671
59962
 
59672
59963
  // src/commands/review.ts
59673
- import { readFileSync as readFileSync18 } from "node:fs";
59964
+ import { readFileSync as readFileSync19 } from "node:fs";
59674
59965
  function requireConfig10() {
59675
59966
  return requireLoginConfig();
59676
59967
  }
@@ -59858,7 +60149,7 @@ function reviewCommand() {
59858
60149
  let body = opts.body;
59859
60150
  if (opts.bodyFile) {
59860
60151
  try {
59861
- body = readFileSync18(opts.bodyFile, "utf-8");
60152
+ body = readFileSync19(opts.bodyFile, "utf-8");
59862
60153
  } catch (err) {
59863
60154
  console.error(import_picocolors25.default.red(`Failed to read --body-file: ${err.message}`));
59864
60155
  process.exit(1);
@@ -60778,16 +61069,16 @@ The coding agent performs triage; Dosu cloud generates docs and opens the PR.
60778
61069
  // src/commands/skill.ts
60779
61070
  import {
60780
61071
  cpSync,
60781
- existsSync as existsSync19,
61072
+ existsSync as existsSync20,
60782
61073
  lstatSync as lstatSync2,
60783
- mkdirSync as mkdirSync11,
60784
- readFileSync as readFileSync19,
61074
+ mkdirSync as mkdirSync12,
61075
+ readFileSync as readFileSync20,
60785
61076
  rmSync as rmSync5,
60786
61077
  symlinkSync,
60787
- writeFileSync as writeFileSync12
61078
+ writeFileSync as writeFileSync13
60788
61079
  } from "node:fs";
60789
61080
  import { homedir as homedir7 } from "node:os";
60790
- import { dirname as dirname10, join as join22, relative as relative3 } from "node:path";
61081
+ import { dirname as dirname10, join as join23, relative as relative3 } from "node:path";
60791
61082
  function skillAgentIDsForProviders(providerIDs) {
60792
61083
  return [
60793
61084
  ...new Set(providerIDs.map((providerID) => SKILL_AGENT_BY_PROVIDER[providerID]).filter((agent) => Boolean(agent)))
@@ -60797,15 +61088,15 @@ function isSkillAgentID(agent) {
60797
61088
  return SUPPORTED_SKILL_AGENTS.includes(agent);
60798
61089
  }
60799
61090
  function universalSkillsDir() {
60800
- return join22(homedir7(), ".agents", "skills");
61091
+ return join23(homedir7(), ".agents", "skills");
60801
61092
  }
60802
61093
  function linkedSkillsDir(agent) {
60803
61094
  if (agent === "claude-code") {
60804
- const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR?.trim() || join22(homedir7(), ".claude");
60805
- return join22(claudeConfigDir, "skills");
61095
+ const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR?.trim() || join23(homedir7(), ".claude");
61096
+ return join23(claudeConfigDir, "skills");
60806
61097
  }
60807
61098
  if (agent === "windsurf")
60808
- return join22(homedir7(), ".codeium", "windsurf", "skills");
61099
+ return join23(homedir7(), ".codeium", "windsurf", "skills");
60809
61100
  return null;
60810
61101
  }
60811
61102
  function skillInstallTargetForProvider(providerID) {
@@ -60814,18 +61105,18 @@ function skillInstallTargetForProvider(providerID) {
60814
61105
  return null;
60815
61106
  const linked = linkedSkillsDir(agentID);
60816
61107
  if (linked)
60817
- return { path: join22(linked, SKILL_NAME), symlink: true };
60818
- return { path: join22(universalSkillsDir(), SKILL_NAME), symlink: false };
61108
+ return { path: join23(linked, SKILL_NAME), symlink: true };
61109
+ return { path: join23(universalSkillsDir(), SKILL_NAME), symlink: false };
60819
61110
  }
60820
61111
  function installStatePath() {
60821
- return join22(getConfigDir(), INSTALL_STATE_FILENAME);
61112
+ return join23(getConfigDir(), INSTALL_STATE_FILENAME);
60822
61113
  }
60823
61114
  function readSkillInstallState() {
60824
61115
  try {
60825
61116
  const path = installStatePath();
60826
- if (!existsSync19(path))
61117
+ if (!existsSync20(path))
60827
61118
  return null;
60828
- const data = JSON.parse(readFileSync19(path, "utf-8"));
61119
+ const data = JSON.parse(readFileSync20(path, "utf-8"));
60829
61120
  if (typeof data?.version === "string" && Array.isArray(data.agents) && data.agents.every((agent) => typeof agent === "string") && typeof data.installedAt === "number") {
60830
61121
  return { version: data.version, agents: data.agents, installedAt: data.installedAt };
60831
61122
  }
@@ -60837,9 +61128,9 @@ function readSkillInstallState() {
60837
61128
  function writeSkillInstallState(state) {
60838
61129
  try {
60839
61130
  const dir = getConfigDir();
60840
- if (!existsSync19(dir))
60841
- mkdirSync11(dir, { recursive: true, mode: 448 });
60842
- writeFileSync12(installStatePath(), JSON.stringify(state), { mode: 384 });
61131
+ if (!existsSync20(dir))
61132
+ mkdirSync12(dir, { recursive: true, mode: 448 });
61133
+ writeFileSync13(installStatePath(), JSON.stringify(state), { mode: 384 });
60843
61134
  } catch (err) {
60844
61135
  logger.debug("skill", `Could not record skill install state: ${err}`);
60845
61136
  }
@@ -60848,11 +61139,11 @@ function clearSkillInstallState() {
60848
61139
  rmSync5(installStatePath(), { force: true });
60849
61140
  }
60850
61141
  function pruneLegacySkillLock() {
60851
- const lockPath = join22(homedir7(), ".agents", ".skill-lock.json");
61142
+ const lockPath = join23(homedir7(), ".agents", ".skill-lock.json");
60852
61143
  try {
60853
- if (!existsSync19(lockPath))
61144
+ if (!existsSync20(lockPath))
60854
61145
  return [];
60855
- const lock = JSON.parse(readFileSync19(lockPath, "utf-8"));
61146
+ const lock = JSON.parse(readFileSync20(lockPath, "utf-8"));
60856
61147
  const skills = lock?.skills;
60857
61148
  if (!skills || typeof skills !== "object")
60858
61149
  return [];
@@ -60861,7 +61152,7 @@ function pruneLegacySkillLock() {
60861
61152
  return [];
60862
61153
  for (const name of legacy)
60863
61154
  delete skills[name];
60864
- writeFileSync12(lockPath, `${JSON.stringify(lock, null, 2)}
61155
+ writeFileSync13(lockPath, `${JSON.stringify(lock, null, 2)}
60865
61156
  `);
60866
61157
  logger.debug("skill", `Removed legacy lock entries: ${legacy.join(", ")}`);
60867
61158
  return legacy;
@@ -60881,13 +61172,13 @@ function pathExists(path) {
60881
61172
  function writeSkillDir(skill, dir) {
60882
61173
  rmSync5(dir, { recursive: true, force: true });
60883
61174
  for (const file of skill.files) {
60884
- const target = join22(dir, ...file.path.split("/"));
60885
- mkdirSync11(dirname10(target), { recursive: true });
60886
- writeFileSync12(target, file.content, { mode: file.executable ? 493 : 420 });
61175
+ const target = join23(dir, ...file.path.split("/"));
61176
+ mkdirSync12(dirname10(target), { recursive: true });
61177
+ writeFileSync13(target, file.content, { mode: file.executable ? 493 : 420 });
60887
61178
  }
60888
61179
  }
60889
61180
  function linkSkillDir(linkPath, targetDir) {
60890
- mkdirSync11(dirname10(linkPath), { recursive: true });
61181
+ mkdirSync12(dirname10(linkPath), { recursive: true });
60891
61182
  rmSync5(linkPath, { recursive: true, force: true });
60892
61183
  try {
60893
61184
  symlinkSync(relative3(dirname10(linkPath), targetDir), linkPath, "dir");
@@ -60920,15 +61211,15 @@ function installBundledSkills(agentIDs) {
60920
61211
  if (bundledNames.has(name))
60921
61212
  continue;
60922
61213
  for (const dir of [universalSkillsDir(), ...linkDirs])
60923
- removeSkillDir(join22(dir, name));
61214
+ removeSkillDir(join23(dir, name));
60924
61215
  }
60925
61216
  const paths = [];
60926
61217
  for (const skill of BUNDLED_SKILLS) {
60927
- const universal = join22(universalSkillsDir(), skill.name);
61218
+ const universal = join23(universalSkillsDir(), skill.name);
60928
61219
  writeSkillDir(skill, universal);
60929
61220
  paths.push(universal);
60930
61221
  for (const dir of linkDirs) {
60931
- const linkPath = join22(dir, skill.name);
61222
+ const linkPath = join23(dir, skill.name);
60932
61223
  linkSkillDir(linkPath, universal);
60933
61224
  paths.push(linkPath);
60934
61225
  }
@@ -60939,7 +61230,7 @@ function installBundledSkills(agentIDs) {
60939
61230
  agents: [...new Set([...previous?.agents ?? [], ...agents])],
60940
61231
  installedAt: Date.now()
60941
61232
  });
60942
- rmSync5(join22(getConfigDir(), LEGACY_CACHE_FILENAME), { force: true });
61233
+ rmSync5(join23(getConfigDir(), LEGACY_CACHE_FILENAME), { force: true });
60943
61234
  logger.info("skill", `Installed bundled skills v${VERSION} for ${agents.join(", ")}`);
60944
61235
  return { success: true, version: VERSION, paths };
60945
61236
  } catch (err) {
@@ -60961,13 +61252,13 @@ function removeSkills() {
60961
61252
  const removed = [];
60962
61253
  for (const dir of dirs) {
60963
61254
  for (const name of names) {
60964
- const path = join22(dir, name);
61255
+ const path = join23(dir, name);
60965
61256
  if (removeSkillDir(path))
60966
61257
  removed.push(path);
60967
61258
  }
60968
61259
  }
60969
61260
  clearSkillInstallState();
60970
- rmSync5(join22(getConfigDir(), LEGACY_CACHE_FILENAME), { force: true });
61261
+ rmSync5(join23(getConfigDir(), LEGACY_CACHE_FILENAME), { force: true });
60971
61262
  return removed;
60972
61263
  }
60973
61264
  function printPaths(paths) {
@@ -61322,17 +61613,17 @@ var init_sources = __esm(() => {
61322
61613
  // src/telemetry/settings.ts
61323
61614
  import { randomUUID as randomUUID4 } from "node:crypto";
61324
61615
  import {
61325
- existsSync as existsSync20,
61616
+ existsSync as existsSync21,
61326
61617
  lstatSync as lstatSync3,
61327
- mkdirSync as mkdirSync12,
61328
- readFileSync as readFileSync20,
61329
- renameSync as renameSync5,
61618
+ mkdirSync as mkdirSync13,
61619
+ readFileSync as readFileSync21,
61620
+ renameSync as renameSync6,
61330
61621
  unlinkSync as unlinkSync4,
61331
- writeFileSync as writeFileSync13
61622
+ writeFileSync as writeFileSync14
61332
61623
  } from "node:fs";
61333
- import { join as join23 } from "node:path";
61624
+ import { join as join24 } from "node:path";
61334
61625
  function getTelemetrySettingsPath() {
61335
- return join23(getConfigDir(), TELEMETRY_SETTINGS_FILENAME);
61626
+ return join24(getConfigDir(), TELEMETRY_SETTINGS_FILENAME);
61336
61627
  }
61337
61628
  function loadTelemetrySettings() {
61338
61629
  return readTelemetrySettings().settings;
@@ -61400,7 +61691,7 @@ function readTelemetrySettings() {
61400
61691
  }
61401
61692
  let content;
61402
61693
  try {
61403
- content = readFileSync20(path, "utf-8");
61694
+ content = readFileSync21(path, "utf-8");
61404
61695
  } catch {
61405
61696
  return { status: "error", settings: disabledTelemetrySettings() };
61406
61697
  }
@@ -61432,14 +61723,14 @@ function writeTelemetrySettings(settings) {
61432
61723
  const dir = getConfigDir();
61433
61724
  const temporaryPath = `${path}.${process.pid}.${randomUUID4()}.tmp`;
61434
61725
  try {
61435
- if (!existsSync20(dir))
61436
- mkdirSync12(dir, { recursive: true, mode: 448 });
61437
- writeFileSync13(temporaryPath, `${JSON.stringify(settings, null, 2)}
61726
+ if (!existsSync21(dir))
61727
+ mkdirSync13(dir, { recursive: true, mode: 448 });
61728
+ writeFileSync14(temporaryPath, `${JSON.stringify(settings, null, 2)}
61438
61729
  `, {
61439
61730
  flag: "wx",
61440
61731
  mode: 384
61441
61732
  });
61442
- renameSync5(temporaryPath, path);
61733
+ renameSync6(temporaryPath, path);
61443
61734
  return true;
61444
61735
  } catch {
61445
61736
  try {
@@ -61820,7 +62111,7 @@ var init_antigravity = __esm(() => {
61820
62111
  });
61821
62112
 
61822
62113
  // src/mcp/providers/claude.ts
61823
- import { join as join24 } from "node:path";
62114
+ import { join as join25 } from "node:path";
61824
62115
  var ClaudeProvider = () => createJSONProvider({
61825
62116
  providerName: "Claude Code",
61826
62117
  providerID: "claude",
@@ -61830,24 +62121,24 @@ var ClaudeProvider = () => createJSONProvider({
61830
62121
  globalPath: "~/.claude.json",
61831
62122
  topKey: "mcpServers",
61832
62123
  buildServer: ({ url, headers }) => ({ type: "http", url, headers, alwaysLoad: true }),
61833
- localConfigPath: (cwd) => join24(cwd, ".mcp.json")
62124
+ localConfigPath: (cwd) => join25(cwd, ".mcp.json")
61834
62125
  });
61835
62126
  var init_claude = __esm(() => {
61836
62127
  init_base();
61837
62128
  });
61838
62129
 
61839
62130
  // src/mcp/providers/claude-desktop.ts
61840
- import { join as join25 } from "node:path";
62131
+ import { join as join26 } from "node:path";
61841
62132
  function configPath() {
61842
- return join25(appSupportDir(), "Claude", "claude_desktop_config.json");
62133
+ return join26(appSupportDir(), "Claude", "claude_desktop_config.json");
61843
62134
  }
61844
62135
  var ClaudeDesktopProvider = () => ({
61845
62136
  name: () => "Claude Desktop",
61846
62137
  id: () => "claude-desktop",
61847
62138
  supportsLocal: () => false,
61848
62139
  priority: () => 2,
61849
- detectPaths: () => [join25(appSupportDir(), "Claude")],
61850
- isInstalled: () => isInstalled([join25(appSupportDir(), "Claude")]),
62140
+ detectPaths: () => [join26(appSupportDir(), "Claude")],
62141
+ isInstalled: () => isInstalled([join26(appSupportDir(), "Claude")]),
61851
62142
  globalConfigPath: () => configPath(),
61852
62143
  isConfigured: () => isJSONKeyConfigured(configPath(), "mcpServers"),
61853
62144
  install(cfg, global2) {
@@ -61874,14 +62165,14 @@ var init_claude_desktop = __esm(() => {
61874
62165
  });
61875
62166
 
61876
62167
  // src/mcp/providers/cline.ts
61877
- import { join as join26 } from "node:path";
61878
- var extensionDir = () => join26(appSupportDir(), "Code", "User", "globalStorage", "saoudrizwan.claude-dev"), ClineProvider = () => createJSONProvider({
62168
+ import { join as join27 } from "node:path";
62169
+ var extensionDir = () => join27(appSupportDir(), "Code", "User", "globalStorage", "saoudrizwan.claude-dev"), ClineProvider = () => createJSONProvider({
61879
62170
  providerName: "Cline",
61880
62171
  providerID: "cline",
61881
62172
  local: false,
61882
62173
  priorityValue: 11,
61883
62174
  paths: [extensionDir()],
61884
- globalPath: join26(extensionDir(), "settings", "cline_mcp_settings.json"),
62175
+ globalPath: join27(extensionDir(), "settings", "cline_mcp_settings.json"),
61885
62176
  topKey: "mcpServers",
61886
62177
  buildServer: ({ url, headers }) => ({
61887
62178
  url,
@@ -61896,7 +62187,7 @@ var init_cline = __esm(() => {
61896
62187
  });
61897
62188
 
61898
62189
  // src/mcp/providers/cline-cli.ts
61899
- import { join as join27 } from "node:path";
62190
+ import { join as join28 } from "node:path";
61900
62191
  function clineDir() {
61901
62192
  return process.env.CLINE_DIR ?? expandHome("~/.cline");
61902
62193
  }
@@ -61906,7 +62197,7 @@ var ClineCliProvider = () => createJSONProvider({
61906
62197
  local: false,
61907
62198
  priorityValue: 12,
61908
62199
  paths: [clineDir()],
61909
- globalPath: join27(clineDir(), "data", "settings", "cline_mcp_settings.json"),
62200
+ globalPath: join28(clineDir(), "data", "settings", "cline_mcp_settings.json"),
61910
62201
  topKey: "mcpServers",
61911
62202
  buildServer: ({ url, headers }) => ({
61912
62203
  url,
@@ -61921,20 +62212,20 @@ var init_cline_cli = __esm(() => {
61921
62212
  });
61922
62213
 
61923
62214
  // src/mcp/providers/codex.ts
61924
- import { existsSync as existsSync21, readFileSync as readFileSync21 } from "node:fs";
61925
- import { dirname as dirname11, join as join28 } from "node:path";
62215
+ import { existsSync as existsSync22, readFileSync as readFileSync22 } from "node:fs";
62216
+ import { dirname as dirname11, join as join29 } from "node:path";
61926
62217
  function codexHome3() {
61927
62218
  return process.env.CODEX_HOME ?? expandHome("~/.codex");
61928
62219
  }
61929
62220
  function getConfigPath2(global2) {
61930
62221
  if (global2)
61931
- return join28(codexHome3(), "config.toml");
61932
- return join28(process.cwd(), ".codex", "config.toml");
62222
+ return join29(codexHome3(), "config.toml");
62223
+ return join29(process.cwd(), ".codex", "config.toml");
61933
62224
  }
61934
62225
  function readTOML(path) {
61935
- if (!existsSync21(path))
62226
+ if (!existsSync22(path))
61936
62227
  return "";
61937
- return readFileSync21(path, "utf-8");
62228
+ return readFileSync22(path, "utf-8");
61938
62229
  }
61939
62230
  function writeTOML(path, content) {
61940
62231
  writeSecureFile(path, content);
@@ -62009,17 +62300,17 @@ function projectConfigPaths() {
62009
62300
  const chain = [];
62010
62301
  for (let dir = cwd;; ) {
62011
62302
  chain.push(dir);
62012
- if (existsSync21(join28(dir, ".git")))
62303
+ if (existsSync22(join29(dir, ".git")))
62013
62304
  break;
62014
62305
  const parent = dirname11(dir);
62015
62306
  if (parent === dir)
62016
- return [join28(cwd, ".codex", "config.toml")];
62307
+ return [join29(cwd, ".codex", "config.toml")];
62017
62308
  dir = parent;
62018
62309
  }
62019
- return chain.reverse().map((dir) => join28(dir, ".codex", "config.toml"));
62310
+ return chain.reverse().map((dir) => join29(dir, ".codex", "config.toml"));
62020
62311
  }
62021
62312
  function pruneLegacyRemoteEntry(path) {
62022
- if (!existsSync21(path))
62313
+ if (!existsSync22(path))
62023
62314
  return;
62024
62315
  const content = readTOML(path);
62025
62316
  if (!hasRemoteHTTPForm(content))
@@ -62033,9 +62324,9 @@ var REMOTE_HTTP_KEY, CodexProvider = () => ({
62033
62324
  priority: () => 8,
62034
62325
  detectPaths: () => ["~/.codex"],
62035
62326
  isInstalled: () => isInstalled(["~/.codex"]),
62036
- globalConfigPath: () => join28(codexHome3(), "config.toml"),
62327
+ globalConfigPath: () => join29(codexHome3(), "config.toml"),
62037
62328
  isConfigured: () => {
62038
- const content = readTOML(join28(codexHome3(), "config.toml"));
62329
+ const content = readTOML(join29(codexHome3(), "config.toml"));
62039
62330
  return content.includes("[mcp_servers.dosu]");
62040
62331
  },
62041
62332
  install(cfg, global2) {
@@ -62066,10 +62357,10 @@ var init_codex = __esm(() => {
62066
62357
  });
62067
62358
 
62068
62359
  // src/mcp/providers/copilot.ts
62069
- import { join as join29 } from "node:path";
62360
+ import { join as join30 } from "node:path";
62070
62361
  function globalPath() {
62071
62362
  if (process.env.XDG_CONFIG_HOME) {
62072
- return join29(process.env.XDG_CONFIG_HOME, "mcp-config.json");
62363
+ return join30(process.env.XDG_CONFIG_HOME, "mcp-config.json");
62073
62364
  }
62074
62365
  return expandHome("~/.copilot/mcp-config.json");
62075
62366
  }
@@ -62093,7 +62384,7 @@ var CopilotProvider = () => ({
62093
62384
  };
62094
62385
  installJSONServer(globalPath(), "mcpServers", server);
62095
62386
  } else {
62096
- const configPath = join29(process.cwd(), ".vscode", "mcp.json");
62387
+ const configPath = join30(process.cwd(), ".vscode", "mcp.json");
62097
62388
  const server = {
62098
62389
  type: "http",
62099
62390
  url,
@@ -62106,7 +62397,7 @@ var CopilotProvider = () => ({
62106
62397
  if (global2) {
62107
62398
  removeJSONServer(globalPath(), "mcpServers");
62108
62399
  } else {
62109
- const configPath = join29(process.cwd(), ".vscode", "mcp.json");
62400
+ const configPath = join30(process.cwd(), ".vscode", "mcp.json");
62110
62401
  removeJSONServer(configPath, "servers");
62111
62402
  }
62112
62403
  }
@@ -62117,7 +62408,7 @@ var init_copilot = __esm(() => {
62117
62408
  });
62118
62409
 
62119
62410
  // src/mcp/providers/cursor.ts
62120
- import { join as join30 } from "node:path";
62411
+ import { join as join31 } from "node:path";
62121
62412
  var CursorProvider = () => createJSONProvider({
62122
62413
  providerName: "Cursor",
62123
62414
  providerID: "cursor",
@@ -62130,14 +62421,14 @@ var CursorProvider = () => createJSONProvider({
62130
62421
  url,
62131
62422
  headers
62132
62423
  }),
62133
- localConfigPath: (cwd) => join30(cwd, ".cursor", "mcp.json")
62424
+ localConfigPath: (cwd) => join31(cwd, ".cursor", "mcp.json")
62134
62425
  });
62135
62426
  var init_cursor = __esm(() => {
62136
62427
  init_base();
62137
62428
  });
62138
62429
 
62139
62430
  // src/mcp/providers/factory.ts
62140
- import { join as join31 } from "node:path";
62431
+ import { join as join32 } from "node:path";
62141
62432
  var FactoryProvider = () => createJSONProvider({
62142
62433
  providerName: "Factory",
62143
62434
  providerID: "factory",
@@ -62146,14 +62437,14 @@ var FactoryProvider = () => createJSONProvider({
62146
62437
  paths: ["~/.factory"],
62147
62438
  globalPath: "~/.factory/mcp.json",
62148
62439
  topKey: "mcpServers",
62149
- localConfigPath: (cwd) => join31(cwd, ".factory", "mcp.json")
62440
+ localConfigPath: (cwd) => join32(cwd, ".factory", "mcp.json")
62150
62441
  });
62151
62442
  var init_factory = __esm(() => {
62152
62443
  init_base();
62153
62444
  });
62154
62445
 
62155
62446
  // src/mcp/providers/gemini.ts
62156
- import { join as join32 } from "node:path";
62447
+ import { join as join33 } from "node:path";
62157
62448
  var GeminiProvider = () => createJSONProvider({
62158
62449
  providerName: "Gemini CLI",
62159
62450
  providerID: "gemini",
@@ -62162,7 +62453,7 @@ var GeminiProvider = () => createJSONProvider({
62162
62453
  paths: ["~/.gemini"],
62163
62454
  globalPath: "~/.gemini/settings.json",
62164
62455
  topKey: "mcpServers",
62165
- localConfigPath: (cwd) => join32(cwd, ".gemini", "settings.json")
62456
+ localConfigPath: (cwd) => join33(cwd, ".gemini", "settings.json")
62166
62457
  });
62167
62458
  var init_gemini = __esm(() => {
62168
62459
  init_base();
@@ -62204,14 +62495,14 @@ var init_manual = __esm(() => {
62204
62495
  });
62205
62496
 
62206
62497
  // src/mcp/providers/mcporter.ts
62207
- import { existsSync as existsSync22 } from "node:fs";
62208
- import { join as join33 } from "node:path";
62498
+ import { existsSync as existsSync23 } from "node:fs";
62499
+ import { join as join34 } from "node:path";
62209
62500
  function resolveGlobalConfigPath() {
62210
62501
  const jsonPath = expandHome("~/.mcporter/mcporter.json");
62211
- if (existsSync22(jsonPath))
62502
+ if (existsSync23(jsonPath))
62212
62503
  return jsonPath;
62213
62504
  const jsoncPath = expandHome("~/.mcporter/mcporter.jsonc");
62214
- if (existsSync22(jsoncPath))
62505
+ if (existsSync23(jsoncPath))
62215
62506
  return jsoncPath;
62216
62507
  return jsonPath;
62217
62508
  }
@@ -62225,7 +62516,7 @@ var MCPorterProvider = () => ({
62225
62516
  globalConfigPath: () => resolveGlobalConfigPath(),
62226
62517
  isConfigured: () => isJSONKeyConfigured(resolveGlobalConfigPath(), "mcpServers"),
62227
62518
  install(cfg, global2) {
62228
- const configPath = global2 ? resolveGlobalConfigPath() : join33(process.cwd(), "config", "mcporter.json");
62519
+ const configPath = global2 ? resolveGlobalConfigPath() : join34(process.cwd(), "config", "mcporter.json");
62229
62520
  const server = {
62230
62521
  type: "http",
62231
62522
  url: mcpEndpoint(cfg),
@@ -62234,7 +62525,7 @@ var MCPorterProvider = () => ({
62234
62525
  installJSONServer(configPath, "mcpServers", server);
62235
62526
  },
62236
62527
  remove(global2) {
62237
- const configPath = global2 ? resolveGlobalConfigPath() : join33(process.cwd(), "config", "mcporter.json");
62528
+ const configPath = global2 ? resolveGlobalConfigPath() : join34(process.cwd(), "config", "mcporter.json");
62238
62529
  removeJSONServer(configPath, "mcpServers");
62239
62530
  }
62240
62531
  });
@@ -62244,7 +62535,7 @@ var init_mcporter = __esm(() => {
62244
62535
  });
62245
62536
 
62246
62537
  // src/mcp/providers/opencode.ts
62247
- import { join as join34 } from "node:path";
62538
+ import { join as join35 } from "node:path";
62248
62539
  var OpenCodeProvider = () => createJSONProvider({
62249
62540
  providerName: "OpenCode",
62250
62541
  providerID: "opencode",
@@ -62259,23 +62550,23 @@ var OpenCodeProvider = () => createJSONProvider({
62259
62550
  enabled: true,
62260
62551
  headers
62261
62552
  }),
62262
- localConfigPath: (cwd) => join34(cwd, "opencode.json")
62553
+ localConfigPath: (cwd) => join35(cwd, "opencode.json")
62263
62554
  });
62264
62555
  var init_opencode = __esm(() => {
62265
62556
  init_base();
62266
62557
  });
62267
62558
 
62268
62559
  // src/mcp/providers/vscode.ts
62269
- import { join as join35 } from "node:path";
62560
+ import { join as join36 } from "node:path";
62270
62561
  var VSCodeProvider = () => createJSONProvider({
62271
62562
  providerName: "VS Code",
62272
62563
  providerID: "vscode",
62273
62564
  local: true,
62274
62565
  priorityValue: 6,
62275
- paths: [join35(appSupportDir(), "Code")],
62276
- globalPath: join35(appSupportDir(), "Code", "User", "mcp.json"),
62566
+ paths: [join36(appSupportDir(), "Code")],
62567
+ globalPath: join36(appSupportDir(), "Code", "User", "mcp.json"),
62277
62568
  topKey: "servers",
62278
- localConfigPath: (cwd) => join35(cwd, ".vscode", "mcp.json")
62569
+ localConfigPath: (cwd) => join36(cwd, ".vscode", "mcp.json")
62279
62570
  });
62280
62571
  var init_vscode = __esm(() => {
62281
62572
  init_detect();
@@ -62284,14 +62575,14 @@ var init_vscode = __esm(() => {
62284
62575
 
62285
62576
  // src/mcp/providers/windsurf.ts
62286
62577
  import { homedir as homedir8 } from "node:os";
62287
- import { join as join36 } from "node:path";
62578
+ import { join as join37 } from "node:path";
62288
62579
  var WindsurfProvider = () => createJSONProvider({
62289
62580
  providerName: "Windsurf",
62290
62581
  providerID: "windsurf",
62291
62582
  local: false,
62292
62583
  priorityValue: 9,
62293
- paths: [join36(homedir8(), ".codeium", "windsurf")],
62294
- globalPath: join36(homedir8(), ".codeium", "windsurf", "mcp_config.json"),
62584
+ paths: [join37(homedir8(), ".codeium", "windsurf")],
62585
+ globalPath: join37(homedir8(), ".codeium", "windsurf", "mcp_config.json"),
62295
62586
  topKey: "mcpServers"
62296
62587
  });
62297
62588
  var init_windsurf = __esm(() => {
@@ -62301,25 +62592,25 @@ var init_windsurf = __esm(() => {
62301
62592
  // src/mcp/providers/zed.ts
62302
62593
  import { rmSync as rmSync6 } from "node:fs";
62303
62594
  import { homedir as homedir9, platform as platform3 } from "node:os";
62304
- import { join as join37 } from "node:path";
62595
+ import { join as join38 } from "node:path";
62305
62596
  function zedConfigDir() {
62306
62597
  const os = platform3();
62307
62598
  if (os === "win32")
62308
- return join37(appSupportDir(), "Zed");
62599
+ return join38(appSupportDir(), "Zed");
62309
62600
  if (os === "darwin")
62310
- return join37(homedir9(), ".config", "zed");
62311
- return join37(appSupportDir(), "zed");
62601
+ return join38(homedir9(), ".config", "zed");
62602
+ return join38(appSupportDir(), "zed");
62312
62603
  }
62313
62604
  function zedDataDir() {
62314
62605
  const os = platform3();
62315
62606
  if (os === "darwin")
62316
- return join37(appSupportDir(), "Zed");
62607
+ return join38(appSupportDir(), "Zed");
62317
62608
  if (os === "win32")
62318
- return join37(process.env.LOCALAPPDATA ?? "", "Zed");
62319
- return join37(process.env.XDG_DATA_HOME ?? join37(homedir9(), ".local", "share"), "zed");
62609
+ return join38(process.env.LOCALAPPDATA ?? "", "Zed");
62610
+ return join38(process.env.XDG_DATA_HOME ?? join38(homedir9(), ".local", "share"), "zed");
62320
62611
  }
62321
62612
  function legacyDarwinSettingsPath() {
62322
- return platform3() === "darwin" ? join37(appSupportDir(), "Zed", "settings.json") : null;
62613
+ return platform3() === "darwin" ? join38(appSupportDir(), "Zed", "settings.json") : null;
62323
62614
  }
62324
62615
  function removeLegacyDosuEntry(path) {
62325
62616
  let cfg;
@@ -62345,10 +62636,10 @@ var ZedProvider = (legacyPath = legacyDarwinSettingsPath()) => {
62345
62636
  local: true,
62346
62637
  priorityValue: 10,
62347
62638
  paths: [zedConfigDir(), zedDataDir()],
62348
- globalPath: join37(zedConfigDir(), "settings.json"),
62639
+ globalPath: join38(zedConfigDir(), "settings.json"),
62349
62640
  topKey: "context_servers",
62350
62641
  buildServer: ({ url, headers }) => ({ url, headers }),
62351
- localConfigPath: (cwd) => join37(cwd, ".zed", "settings.json")
62642
+ localConfigPath: (cwd) => join38(cwd, ".zed", "settings.json")
62352
62643
  });
62353
62644
  if (!legacyPath)
62354
62645
  return provider;
@@ -62456,29 +62747,29 @@ var init_refresh = __esm(() => {
62456
62747
  import { spawn as spawn3 } from "node:child_process";
62457
62748
  import {
62458
62749
  closeSync as closeSync6,
62459
- existsSync as existsSync23,
62460
- mkdirSync as mkdirSync13,
62750
+ existsSync as existsSync24,
62751
+ mkdirSync as mkdirSync14,
62461
62752
  openSync as openSync6,
62462
- readFileSync as readFileSync22,
62753
+ readFileSync as readFileSync23,
62463
62754
  rmSync as rmSync7,
62464
62755
  statSync as statSync8,
62465
- writeFileSync as writeFileSync14,
62756
+ writeFileSync as writeFileSync15,
62466
62757
  writeSync
62467
62758
  } from "node:fs";
62468
62759
  import { homedir as homedir10 } from "node:os";
62469
- import { join as join38 } from "node:path";
62760
+ import { join as join39 } from "node:path";
62470
62761
  function statePath() {
62471
- return join38(getConfigDir(), STATE_FILENAME2);
62762
+ return join39(getConfigDir(), STATE_FILENAME2);
62472
62763
  }
62473
62764
  function lockPath2() {
62474
- return join38(getConfigDir(), LOCK_FILENAME2);
62765
+ return join39(getConfigDir(), LOCK_FILENAME2);
62475
62766
  }
62476
62767
  function isValidVersion(value) {
62477
62768
  return typeof value === "string" && VERSION_PATTERN.test(value);
62478
62769
  }
62479
62770
  function readState() {
62480
62771
  try {
62481
- const raw = JSON.parse(readFileSync22(statePath(), "utf-8"));
62772
+ const raw = JSON.parse(readFileSync23(statePath(), "utf-8"));
62482
62773
  if (typeof raw !== "object" || raw === null || Array.isArray(raw))
62483
62774
  return {};
62484
62775
  const data = raw;
@@ -62497,9 +62788,9 @@ function readState() {
62497
62788
  function writeState(state) {
62498
62789
  try {
62499
62790
  const dir = getConfigDir();
62500
- if (!existsSync23(dir))
62501
- mkdirSync13(dir, { recursive: true, mode: 448 });
62502
- writeFileSync14(statePath(), `${JSON.stringify(state, null, 2)}
62791
+ if (!existsSync24(dir))
62792
+ mkdirSync14(dir, { recursive: true, mode: 448 });
62793
+ writeFileSync15(statePath(), `${JSON.stringify(state, null, 2)}
62503
62794
  `, { mode: 384 });
62504
62795
  return true;
62505
62796
  } catch {
@@ -62552,7 +62843,7 @@ function lockIsFresh(now) {
62552
62843
  }
62553
62844
  function claimLock(version, now) {
62554
62845
  try {
62555
- mkdirSync13(getConfigDir(), { recursive: true, mode: 448 });
62846
+ mkdirSync14(getConfigDir(), { recursive: true, mode: 448 });
62556
62847
  if (!lockIsFresh(now))
62557
62848
  rmSync7(lockPath2(), { force: true });
62558
62849
  const fd = openSync6(lockPath2(), "wx", 384);
@@ -62573,7 +62864,7 @@ function releaseLock() {
62573
62864
  }
62574
62865
  function readLockVersion() {
62575
62866
  try {
62576
- const version = readFileSync22(lockPath2(), "utf-8").trim();
62867
+ const version = readFileSync23(lockPath2(), "utf-8").trim();
62577
62868
  return isValidVersion(version) ? version : undefined;
62578
62869
  } catch {
62579
62870
  return;
@@ -62647,8 +62938,8 @@ var init_auto_update = __esm(() => {
62647
62938
  });
62648
62939
 
62649
62940
  // src/version/update-check.ts
62650
- import { existsSync as existsSync24, mkdirSync as mkdirSync14, readFileSync as readFileSync23, writeFileSync as writeFileSync15 } from "node:fs";
62651
- import { join as join39 } from "node:path";
62941
+ import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync24, writeFileSync as writeFileSync16 } from "node:fs";
62942
+ import { join as join40 } from "node:path";
62652
62943
  function isValidVersion2(value) {
62653
62944
  return typeof value === "string" && SEMVER_PATTERN.test(value);
62654
62945
  }
@@ -62670,14 +62961,14 @@ function isNewerVersion(latest, current) {
62670
62961
  return false;
62671
62962
  }
62672
62963
  function getCachePath2() {
62673
- return join39(getConfigDir(), CACHE_FILENAME3);
62964
+ return join40(getConfigDir(), CACHE_FILENAME3);
62674
62965
  }
62675
62966
  function readCache() {
62676
62967
  try {
62677
62968
  const path = getCachePath2();
62678
- if (!existsSync24(path))
62969
+ if (!existsSync25(path))
62679
62970
  return null;
62680
- const data = JSON.parse(readFileSync23(path, "utf-8"));
62971
+ const data = JSON.parse(readFileSync24(path, "utf-8"));
62681
62972
  if (typeof data.lastCheck === "number" && isValidVersion2(data.latestVersion)) {
62682
62973
  return data;
62683
62974
  }
@@ -62689,10 +62980,10 @@ function readCache() {
62689
62980
  function writeCache(cache) {
62690
62981
  try {
62691
62982
  const dir = getConfigDir();
62692
- if (!existsSync24(dir)) {
62693
- mkdirSync14(dir, { recursive: true, mode: 448 });
62983
+ if (!existsSync25(dir)) {
62984
+ mkdirSync15(dir, { recursive: true, mode: 448 });
62694
62985
  }
62695
- writeFileSync15(getCachePath2(), JSON.stringify(cache), { mode: 384 });
62986
+ writeFileSync16(getCachePath2(), JSON.stringify(cache), { mode: 384 });
62696
62987
  } catch {}
62697
62988
  }
62698
62989
  async function fetchLatestVersion() {
@@ -62820,8 +63111,8 @@ var init_update_check = __esm(() => {
62820
63111
  });
62821
63112
 
62822
63113
  // src/version/mcp-refresh-check.ts
62823
- import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync24, writeFileSync as writeFileSync16 } from "node:fs";
62824
- import { join as join40 } from "node:path";
63114
+ import { existsSync as existsSync26, mkdirSync as mkdirSync16, readFileSync as readFileSync25, writeFileSync as writeFileSync17 } from "node:fs";
63115
+ import { join as join41 } from "node:path";
62825
63116
  function needsMcpRefresh(previous, current) {
62826
63117
  if (previous === null)
62827
63118
  return true;
@@ -62831,14 +63122,14 @@ function needsMcpRefresh(previous, current) {
62831
63122
  return MCP_FORMAT_CHANGES.some((change) => isNewerVersion(change, older) && !isNewerVersion(change, newer));
62832
63123
  }
62833
63124
  function getCachePath3() {
62834
- return join40(getConfigDir(), CACHE_FILENAME4);
63125
+ return join41(getConfigDir(), CACHE_FILENAME4);
62835
63126
  }
62836
63127
  function readMcpRefreshCache() {
62837
63128
  try {
62838
63129
  const path = getCachePath3();
62839
- if (!existsSync25(path))
63130
+ if (!existsSync26(path))
62840
63131
  return null;
62841
- const data = JSON.parse(readFileSync24(path, "utf-8"));
63132
+ const data = JSON.parse(readFileSync25(path, "utf-8"));
62842
63133
  if (typeof data?.version === "string")
62843
63134
  return { version: data.version };
62844
63135
  return null;
@@ -62849,10 +63140,10 @@ function readMcpRefreshCache() {
62849
63140
  function writeMcpRefreshCache(cache) {
62850
63141
  try {
62851
63142
  const dir = getConfigDir();
62852
- if (!existsSync25(dir)) {
62853
- mkdirSync15(dir, { recursive: true, mode: 448 });
63143
+ if (!existsSync26(dir)) {
63144
+ mkdirSync16(dir, { recursive: true, mode: 448 });
62854
63145
  }
62855
- writeFileSync16(getCachePath3(), JSON.stringify(cache), { mode: 384 });
63146
+ writeFileSync17(getCachePath3(), JSON.stringify(cache), { mode: 384 });
62856
63147
  } catch {}
62857
63148
  }
62858
63149
  function canRefreshMcp(cfg) {
@@ -62939,7 +63230,7 @@ var init_skill_update_check = __esm(() => {
62939
63230
 
62940
63231
  // src/auth/errors.ts
62941
63232
  var OAuthCallbackError;
62942
- var init_errors3 = __esm(() => {
63233
+ var init_errors4 = __esm(() => {
62943
63234
  OAuthCallbackError = class OAuthCallbackError extends Error {
62944
63235
  error;
62945
63236
  errorCode;
@@ -63000,15 +63291,15 @@ function createLogFollower(path, emit) {
63000
63291
  var init_follow = () => {};
63001
63292
 
63002
63293
  // src/sessions/session-title.ts
63003
- import { existsSync as existsSync26, mkdirSync as mkdirSync16, readFileSync as readFileSync25, renameSync as renameSync6, statSync as statSync10, writeFileSync as writeFileSync17 } from "node:fs";
63294
+ import { existsSync as existsSync27, mkdirSync as mkdirSync17, readFileSync as readFileSync26, renameSync as renameSync7, statSync as statSync10, writeFileSync as writeFileSync18 } from "node:fs";
63004
63295
  import { homedir as homedir11 } from "node:os";
63005
- import { join as join41 } from "node:path";
63296
+ import { join as join42 } from "node:path";
63006
63297
  function cachePath2(configDir) {
63007
- return join41(configDir, CACHE_FILENAME5);
63298
+ return join42(configDir, CACHE_FILENAME5);
63008
63299
  }
63009
63300
  function loadCacheFile2(configDir) {
63010
63301
  try {
63011
- const raw = JSON.parse(readFileSync25(cachePath2(configDir), "utf-8"));
63302
+ const raw = JSON.parse(readFileSync26(cachePath2(configDir), "utf-8"));
63012
63303
  if (raw.schema_version !== CACHE_SCHEMA_VERSION2 || typeof raw.entries !== "object")
63013
63304
  return {};
63014
63305
  return raw.entries;
@@ -63018,13 +63309,13 @@ function loadCacheFile2(configDir) {
63018
63309
  }
63019
63310
  function saveCacheFile2(configDir, entries) {
63020
63311
  try {
63021
- if (!existsSync26(configDir))
63022
- mkdirSync16(configDir, { recursive: true, mode: 448 });
63312
+ if (!existsSync27(configDir))
63313
+ mkdirSync17(configDir, { recursive: true, mode: 448 });
63023
63314
  const path = cachePath2(configDir);
63024
63315
  const tmp = `${path}.${process.pid}.tmp`;
63025
63316
  const file = { schema_version: CACHE_SCHEMA_VERSION2, entries };
63026
- writeFileSync17(tmp, JSON.stringify(file), { mode: 384 });
63027
- renameSync6(tmp, path);
63317
+ writeFileSync18(tmp, JSON.stringify(file), { mode: 384 });
63318
+ renameSync7(tmp, path);
63028
63319
  } catch {}
63029
63320
  }
63030
63321
  function extractUserQuery(text) {
@@ -63056,15 +63347,15 @@ function claudeSummaryFromHead(text) {
63056
63347
  }
63057
63348
  return null;
63058
63349
  }
63059
- function reconstructSession(harness, id, slug, home = homedir11(), exists = existsSync26) {
63350
+ function reconstructSession(harness, id, slug, home = homedir11(), exists = existsSync27) {
63060
63351
  if (!slug)
63061
63352
  return null;
63062
63353
  const candidates = [];
63063
63354
  if (harness === "claude") {
63064
- candidates.push(join41(home, ".claude", "projects", slug, `${id}.jsonl`));
63355
+ candidates.push(join42(home, ".claude", "projects", slug, `${id}.jsonl`));
63065
63356
  } else if (harness === "cursor") {
63066
- const project = join41(home, ".cursor", "projects", slug);
63067
- candidates.push(join41(project, "agent-transcripts", id, `${id}.jsonl`), join41(project, "agent-transcripts", `${id}.jsonl`));
63357
+ const project = join42(home, ".cursor", "projects", slug);
63358
+ candidates.push(join42(project, "agent-transcripts", id, `${id}.jsonl`), join42(project, "agent-transcripts", `${id}.jsonl`));
63068
63359
  } else {
63069
63360
  return null;
63070
63361
  }
@@ -63076,7 +63367,7 @@ function reconstructSession(harness, id, slug, home = homedir11(), exists = exis
63076
63367
  }
63077
63368
  function readHead2(path) {
63078
63369
  try {
63079
- return readFileSync25(path, "utf-8").slice(0, 128 * 1024);
63370
+ return readFileSync26(path, "utf-8").slice(0, 128 * 1024);
63080
63371
  } catch {
63081
63372
  return null;
63082
63373
  }
@@ -63156,8 +63447,8 @@ var init_alt_screen = __esm(() => {
63156
63447
  });
63157
63448
 
63158
63449
  // src/tui/activity-view.ts
63159
- import { existsSync as existsSync27, readFileSync as readFileSync26 } from "node:fs";
63160
- import { basename as basename5 } from "node:path";
63450
+ import { existsSync as existsSync28, readFileSync as readFileSync27 } from "node:fs";
63451
+ import { basename as basename6 } from "node:path";
63161
63452
  function reduceActivityViewKey(key) {
63162
63453
  if (key === "q" || key === ESC7 || key === CTRL_C4)
63163
63454
  return "back";
@@ -63477,12 +63768,12 @@ function createRowNamer() {
63477
63768
  names.titles[key] = t;
63478
63769
  };
63479
63770
  for (const s of [...backlog.queued, ...backlog.open]) {
63480
- if (!existsSync27(s.path))
63771
+ if (!existsSync28(s.path))
63481
63772
  continue;
63482
63773
  const key = `${s.harness}/${s.id}`;
63483
63774
  const dir = dirs.resolve(s);
63484
63775
  if (dir)
63485
- names.projects[key] = basename5(dir);
63776
+ names.projects[key] = basename6(dir);
63486
63777
  title(key, s);
63487
63778
  resolved = true;
63488
63779
  }
@@ -63491,7 +63782,7 @@ function createRowNamer() {
63491
63782
  if (!names.projects[key]) {
63492
63783
  const dir = dirs.cached(key) ?? (r.project ? fromSlug(r.project) : null);
63493
63784
  if (dir)
63494
- names.projects[key] = basename5(dir);
63785
+ names.projects[key] = basename6(dir);
63495
63786
  }
63496
63787
  if (!names.titles[key]) {
63497
63788
  const hit = titles.cached(key);
@@ -63514,7 +63805,7 @@ function createRowNamer() {
63514
63805
  }
63515
63806
  function defaultReadLog2() {
63516
63807
  try {
63517
- return readFileSync26(logger.getLogPath(), "utf-8");
63808
+ return readFileSync27(logger.getLogPath(), "utf-8");
63518
63809
  } catch {
63519
63810
  return "";
63520
63811
  }
@@ -63731,14 +64022,14 @@ var init_activity_view = __esm(() => {
63731
64022
  });
63732
64023
 
63733
64024
  // src/rules/installer.ts
63734
- import { existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as readFileSync27, unlinkSync as unlinkSync5, writeFileSync as writeFileSync18 } from "node:fs";
64025
+ import { existsSync as existsSync29, mkdirSync as mkdirSync18, readFileSync as readFileSync28, unlinkSync as unlinkSync5, writeFileSync as writeFileSync19 } from "node:fs";
63735
64026
  import { homedir as homedir12 } from "node:os";
63736
- import { dirname as dirname12, join as join42 } from "node:path";
64027
+ import { dirname as dirname12, join as join43 } from "node:path";
63737
64028
  function claudeConfigDir4() {
63738
- return process.env.CLAUDE_CONFIG_DIR || join42(homedir12(), ".claude");
64029
+ return process.env.CLAUDE_CONFIG_DIR || join43(homedir12(), ".claude");
63739
64030
  }
63740
64031
  function codexHome4() {
63741
- return process.env.CODEX_HOME || join42(homedir12(), ".codex");
64032
+ return process.env.CODEX_HOME || join43(homedir12(), ".codex");
63742
64033
  }
63743
64034
  function isRuleAgent(agent) {
63744
64035
  return Object.hasOwn(RULE_TARGETS, agent);
@@ -63764,17 +64055,17 @@ async function fetchDosuRule(fetchImpl = globalThis.fetch) {
63764
64055
  return normalizeRule(FALLBACK_DOSU_RULE);
63765
64056
  }
63766
64057
  function ensureParent(path) {
63767
- mkdirSync17(dirname12(path), { recursive: true });
64058
+ mkdirSync18(dirname12(path), { recursive: true });
63768
64059
  }
63769
64060
  function writeIfChanged(path, content) {
63770
- if (!existsSync28(path)) {
64061
+ if (!existsSync29(path)) {
63771
64062
  ensureParent(path);
63772
- writeFileSync18(path, content, "utf-8");
64063
+ writeFileSync19(path, content, "utf-8");
63773
64064
  return "created";
63774
64065
  }
63775
- if (readFileSync27(path, "utf-8") === content)
64066
+ if (readFileSync28(path, "utf-8") === content)
63776
64067
  return "unchanged";
63777
- writeFileSync18(path, content, "utf-8");
64068
+ writeFileSync19(path, content, "utf-8");
63778
64069
  return "updated";
63779
64070
  }
63780
64071
  function findSection(content) {
@@ -63800,14 +64091,14 @@ function buildSection(content, lineEnding = `
63800
64091
  return `${DOSU_RULE_SECTION_START}${lineEnding}${body}${lineEnding}${DOSU_RULE_SECTION_END}`;
63801
64092
  }
63802
64093
  function upsertSection(path, content) {
63803
- if (!existsSync28(path)) {
64094
+ if (!existsSync29(path)) {
63804
64095
  const section = buildSection(content);
63805
64096
  ensureParent(path);
63806
- writeFileSync18(path, `${section}
64097
+ writeFileSync19(path, `${section}
63807
64098
  `, "utf-8");
63808
64099
  return "created";
63809
64100
  }
63810
- const existing = readFileSync27(path, "utf-8");
64101
+ const existing = readFileSync28(path, "utf-8");
63811
64102
  const lineEnding = lineEndingFor(existing);
63812
64103
  const section = buildSection(content, lineEnding);
63813
64104
  const location = findSection(existing);
@@ -63820,7 +64111,7 @@ function upsertSection(path, content) {
63820
64111
  }
63821
64112
  if (next === existing)
63822
64113
  return "unchanged";
63823
- writeFileSync18(path, next, "utf-8");
64114
+ writeFileSync19(path, next, "utf-8");
63824
64115
  return "updated";
63825
64116
  }
63826
64117
  function installRuleForAgent(agent, content) {
@@ -63837,13 +64128,13 @@ function removeRuleForAgent(agent) {
63837
64128
  return null;
63838
64129
  const target = RULE_TARGETS[agent];
63839
64130
  const path = target.path();
63840
- if (!existsSync28(path))
64131
+ if (!existsSync29(path))
63841
64132
  return { agent, path, action: "not_found" };
63842
64133
  if (target.kind === "file") {
63843
64134
  unlinkSync5(path);
63844
64135
  return { agent, path, action: "removed" };
63845
64136
  }
63846
- const existing = readFileSync27(path, "utf-8");
64137
+ const existing = readFileSync28(path, "utf-8");
63847
64138
  const lineEnding = lineEndingFor(existing);
63848
64139
  const location = findSection(existing);
63849
64140
  if (!location)
@@ -63852,7 +64143,7 @@ function removeRuleForAgent(agent) {
63852
64143
  if (!next) {
63853
64144
  unlinkSync5(path);
63854
64145
  } else {
63855
- writeFileSync18(path, `${next}${lineEnding}`, "utf-8");
64146
+ writeFileSync19(path, `${next}${lineEnding}`, "utf-8");
63856
64147
  }
63857
64148
  return { agent, path, action: "removed" };
63858
64149
  }
@@ -63880,36 +64171,36 @@ var init_installer = __esm(() => {
63880
64171
  RULE_TARGETS = {
63881
64172
  claude: {
63882
64173
  kind: "file",
63883
- path: () => join42(claudeConfigDir4(), "rules", "dosu.md")
64174
+ path: () => join43(claudeConfigDir4(), "rules", "dosu.md")
63884
64175
  },
63885
64176
  cursor: {
63886
64177
  kind: "file",
63887
- path: () => join42(homedir12(), ".cursor", "rules", "dosu.mdc"),
64178
+ path: () => join43(homedir12(), ".cursor", "rules", "dosu.mdc"),
63888
64179
  cursorFrontmatter: true
63889
64180
  },
63890
64181
  codex: {
63891
64182
  kind: "section",
63892
- path: () => join42(codexHome4(), "AGENTS.md")
64183
+ path: () => join43(codexHome4(), "AGENTS.md")
63893
64184
  },
63894
64185
  opencode: {
63895
64186
  kind: "section",
63896
- path: () => join42(homedir12(), ".config", "opencode", "AGENTS.md")
64187
+ path: () => join43(homedir12(), ".config", "opencode", "AGENTS.md")
63897
64188
  },
63898
64189
  gemini: {
63899
64190
  kind: "section",
63900
- path: () => join42(homedir12(), ".gemini", "GEMINI.md")
64191
+ path: () => join43(homedir12(), ".gemini", "GEMINI.md")
63901
64192
  },
63902
64193
  antigravity: {
63903
64194
  kind: "section",
63904
- path: () => join42(homedir12(), ".gemini", "GEMINI.md")
64195
+ path: () => join43(homedir12(), ".gemini", "GEMINI.md")
63905
64196
  }
63906
64197
  };
63907
64198
  });
63908
64199
 
63909
64200
  // src/setup/agents-md-step.ts
63910
64201
  import { execSync as execSync2 } from "node:child_process";
63911
- import { existsSync as existsSync29, readFileSync as readFileSync28, writeFileSync as writeFileSync19 } from "node:fs";
63912
- import { join as join43 } from "node:path";
64202
+ import { existsSync as existsSync30, readFileSync as readFileSync29, writeFileSync as writeFileSync20 } from "node:fs";
64203
+ import { join as join44 } from "node:path";
63913
64204
  function inGitWorkTree(cwd = process.cwd()) {
63914
64205
  try {
63915
64206
  const stdout = execSync2("git rev-parse --is-inside-work-tree", {
@@ -63923,10 +64214,10 @@ function inGitWorkTree(cwd = process.cwd()) {
63923
64214
  }
63924
64215
  function dosuAgentsSectionState(cwd = process.cwd()) {
63925
64216
  try {
63926
- const path = join43(cwd, "AGENTS.md");
63927
- if (!existsSync29(path))
64217
+ const path = join44(cwd, "AGENTS.md");
64218
+ if (!existsSync30(path))
63928
64219
  return "missing";
63929
- const content = readFileSync28(path, "utf-8");
64220
+ const content = readFileSync29(path, "utf-8");
63930
64221
  const startMatch = content.match(SECTION_START_RE);
63931
64222
  if (!startMatch || !content.includes(DOSU_SECTION_END))
63932
64223
  return "missing";
@@ -63961,14 +64252,14 @@ function findSection2(content) {
63961
64252
  return { start, end };
63962
64253
  }
63963
64254
  function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RULE) {
63964
- const path = join43(cwd, "AGENTS.md");
63965
- if (!existsSync29(path)) {
64255
+ const path = join44(cwd, "AGENTS.md");
64256
+ if (!existsSync30(path)) {
63966
64257
  const section = buildDosuAgentsSection(content);
63967
- writeFileSync19(path, `${section}
64258
+ writeFileSync20(path, `${section}
63968
64259
  `);
63969
64260
  return { path, action: "created" };
63970
64261
  }
63971
- const existing = readFileSync28(path, "utf-8");
64262
+ const existing = readFileSync29(path, "utf-8");
63972
64263
  const lineEnding = lineEndingFor2(existing);
63973
64264
  const section = renderDosuAgentsSection(content, lineEnding);
63974
64265
  const location = findSection2(existing);
@@ -63980,7 +64271,7 @@ function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RU
63980
64271
  }
63981
64272
  if (next === existing)
63982
64273
  return { path, action: "unchanged" };
63983
- writeFileSync19(path, next);
64274
+ writeFileSync20(path, next);
63984
64275
  return { path, action: "updated" };
63985
64276
  }
63986
64277
  async function stepUpdateAgentsMd(cwd = process.cwd(), content) {
@@ -64589,7 +64880,7 @@ if (hash) {
64589
64880
  </html>`, SUCCESS_COPY;
64590
64881
  var init_server = __esm(() => {
64591
64882
  init_logger();
64592
- init_errors3();
64883
+ init_errors4();
64593
64884
  SUCCESS_COPY = {
64594
64885
  auth: {
64595
64886
  title: "Dosu CLI - Authentication Successful",
@@ -64754,9 +65045,6 @@ async function runSetupFlow(opts = {}) {
64754
65045
  if (cfg.mode !== MODE_OSS) {
64755
65046
  await stepShowLibrary(cfg);
64756
65047
  }
64757
- if (cfg.mode !== MODE_OSS) {
64758
- await stepOfferGithubConnect(cfg);
64759
- }
64760
65048
  const apiKey = await stepMintAPIKey(apiClient, cfg);
64761
65049
  if (!apiKey) {
64762
65050
  trackInBackground(trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_failed", {
@@ -65071,7 +65359,7 @@ async function stepSetupHandshake(cfg, onboardingRunID) {
65071
65359
  const msg = err instanceof Error ? err.message : String(err);
65072
65360
  logger.warn("setup", `Setup handshake did not complete: ${msg}`);
65073
65361
  s.stop("Setup not completed");
65074
- await Promise.resolve().then(() => init_errors3());
65362
+ await Promise.resolve().then(() => init_errors4());
65075
65363
  if (err instanceof OAuthCallbackError) {
65076
65364
  log2.error(err.userMessage);
65077
65365
  return false;
@@ -65080,46 +65368,6 @@ async function stepSetupHandshake(cfg, onboardingRunID) {
65080
65368
  return false;
65081
65369
  }
65082
65370
  }
65083
- async function stepOfferGithubConnect(cfg) {
65084
- const target = cfg.active_account?.target;
65085
- if (!target?.org_id || !target?.space_id)
65086
- return;
65087
- try {
65088
- await Promise.resolve().then(() => init_trpc());
65089
- const trpc = createTypedClient(cfg);
65090
- if (await spaceHasGithubSource(trpc, target.space_id))
65091
- return;
65092
- } catch (err) {
65093
- const msg = err instanceof Error ? err.message : String(err);
65094
- logger.warn("setup", `GitHub source check failed, skipping offer: ${msg}`);
65095
- return;
65096
- }
65097
- logger.info("setup", "Step: offer GitHub connect (no GitHub source in the MCP's Library)");
65098
- log2.warn("No GitHub repos are connected to this MCP yet, so it can't answer from your code.");
65099
- const connectNow = await confirm2({
65100
- message: "Connect a GitHub repo now?",
65101
- active: "Connect now",
65102
- inactive: "Skip for now",
65103
- initialValue: true
65104
- });
65105
- if (isCancel2(connectNow) || !connectNow) {
65106
- log2.info(`Skipped. Connect later at ${info(`${getWebAppURL()}/libraries`)} or re-run ${info("dosu setup")}.`);
65107
- return;
65108
- }
65109
- await stepConnectGitHubRepo(cfg);
65110
- }
65111
- async function spaceHasGithubSource(trpc, spaceID) {
65112
- try {
65113
- const sources = await trpc.libraries.sourcesList.query(spaceID);
65114
- return (sources ?? []).some((source) => source.provider_slug === "github");
65115
- } catch (err) {
65116
- const missingProcedure = isTRPCClientError(err) && err.data?.code === "NOT_FOUND";
65117
- if (!missingProcedure)
65118
- throw err;
65119
- const spaceDeployments = await trpc.workspaces.listForSpace.query(spaceID);
65120
- return (spaceDeployments ?? []).some((d) => d.provider_slug === "github");
65121
- }
65122
- }
65123
65371
  async function resolveCloudSetupContext(cfg) {
65124
65372
  try {
65125
65373
  await Promise.resolve().then(() => init_trpc());
@@ -65652,8 +65900,7 @@ ${dim(wrapLog("Run it inside a session to keep that session out of studying. Rem
65652
65900
  }
65653
65901
  var import_picocolors34, OAUTH_ANALYTICS_REASONS, SETUP_HANDSHAKE_TIMEOUT_MS = 1800000, LIBRARY_SELECT_CANCELLED;
65654
65902
  var init_flow2 = __esm(() => {
65655
- init_dist();
65656
- init_errors3();
65903
+ init_errors4();
65657
65904
  init_client();
65658
65905
  init_skill();
65659
65906
  init_config();
@@ -65672,7 +65919,6 @@ var init_flow2 = __esm(() => {
65672
65919
  init_mcp_refresh_check();
65673
65920
  init_agents_md_step();
65674
65921
  init_analytics2();
65675
- init_github_step();
65676
65922
  init_rules_step();
65677
65923
  init_styles();
65678
65924
  import_picocolors34 = __toESM(require_picocolors(), 1);
@@ -66664,7 +66910,7 @@ var init_pages_view = __esm(() => {
66664
66910
  });
66665
66911
 
66666
66912
  // src/tui/tui.ts
66667
- import { basename as basename6 } from "node:path";
66913
+ import { basename as basename7 } from "node:path";
66668
66914
  async function probeSession(cfg) {
66669
66915
  if (!isAuthenticated(cfg) || !isTokenExpired(cfg))
66670
66916
  return { expired: false };
@@ -66691,7 +66937,7 @@ function bannerContext(cfg, session) {
66691
66937
  return {
66692
66938
  version: getVersionString(),
66693
66939
  webAppHost,
66694
- directory: basename6(process.cwd()),
66940
+ directory: basename7(process.cwd()),
66695
66941
  signedIn: isAuthenticated(cfg),
66696
66942
  sessionExpired: session.expired,
66697
66943
  deploymentName: cfg.active_account?.target?.deployment_name,
@@ -66992,7 +67238,7 @@ async function handleAuthenticate(cfg) {
66992
67238
  });
66993
67239
  saveConfig(cfg);
66994
67240
  } catch (err) {
66995
- await Promise.resolve().then(() => init_errors3());
67241
+ await Promise.resolve().then(() => init_errors4());
66996
67242
  if (err instanceof OAuthCallbackError) {
66997
67243
  log2.error(err.userMessage);
66998
67244
  return;
@@ -67638,7 +67884,7 @@ var init_flow3 = __esm(() => {
67638
67884
  });
67639
67885
 
67640
67886
  // src/cli/cli.ts
67641
- import { readFileSync as readFileSync29, unlinkSync as unlinkSync6 } from "node:fs";
67887
+ import { readFileSync as readFileSync30, unlinkSync as unlinkSync6 } from "node:fs";
67642
67888
  function shouldRunBackgroundChecks(actionName) {
67643
67889
  return actionName !== "upgrade";
67644
67890
  }
@@ -67820,7 +68066,7 @@ Run 'dosu --help' to see available commands.`;
67820
68066
  }
67821
68067
  await Promise.resolve();
67822
68068
  const useDeviceFlow = !opts.browser || isHeadless();
67823
- await Promise.resolve().then(() => init_errors3());
68069
+ await Promise.resolve().then(() => init_errors4());
67824
68070
  let token;
67825
68071
  if (useDeviceFlow) {
67826
68072
  await Promise.resolve().then(() => init_device());
@@ -68084,7 +68330,7 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
68084
68330
  }
68085
68331
  if (opts.follow) {
68086
68332
  try {
68087
- const lines = readFileSync29(logPath, "utf-8").split(`
68333
+ const lines = readFileSync30(logPath, "utf-8").split(`
68088
68334
  `);
68089
68335
  if (lines.at(-1) === "")
68090
68336
  lines.pop();
@@ -68100,7 +68346,7 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
68100
68346
  if (opts.tail !== undefined) {
68101
68347
  const n = typeof opts.tail === "string" ? parseInt(opts.tail, 10) || 50 : 50;
68102
68348
  try {
68103
- const content = readFileSync29(logPath, "utf-8");
68349
+ const content = readFileSync30(logPath, "utf-8");
68104
68350
  const lines = content.split(`
68105
68351
  `);
68106
68352
  console.log(lines.slice(-n).join(`
@@ -68152,7 +68398,7 @@ function processCommandTelemetry() {
68152
68398
  return;
68153
68399
  }
68154
68400
  }
68155
- var TELEMETRY_FLUSH_TIMEOUT_MS = 750, CliUsageError, FOLLOW_POLL_MS = 500, DEFAULT_TAIL_LINES = 50;
68401
+ var TELEMETRY_FLUSH_TIMEOUT_MS = 750, FOLLOW_POLL_MS = 500, DEFAULT_TAIL_LINES = 50;
68156
68402
  var init_cli = __esm(() => {
68157
68403
  init_commander();
68158
68404
  init_client();
@@ -68186,13 +68432,7 @@ var init_cli = __esm(() => {
68186
68432
  init_pending_tasks_check();
68187
68433
  init_skill_update_check();
68188
68434
  init_update_check();
68189
- CliUsageError = class CliUsageError extends Error {
68190
- exitCode = 1;
68191
- constructor(message) {
68192
- super(message);
68193
- this.name = "CliUsageError";
68194
- }
68195
- };
68435
+ init_errors();
68196
68436
  });
68197
68437
 
68198
68438
  // src/statusline/argv.ts
@@ -68226,4 +68466,4 @@ main().catch((err) => {
68226
68466
  process.exit(1);
68227
68467
  });
68228
68468
 
68229
- //# debugId=01f74cf6-cdbb-b296-6475-6e2164756e21
68469
+ //# debugId=49497211-cd7a-a697-6475-6e2164756e21