@essentialai/cogent-bridge-bundled 3.20.6 → 3.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/cogent-bridge.mjs +337 -161
  2. package/package.json +1 -1
package/cogent-bridge.mjs CHANGED
@@ -1259,8 +1259,8 @@ var init_parseUtil = __esm({
1259
1259
  init_errors();
1260
1260
  init_en();
1261
1261
  makeIssue = (params) => {
1262
- const { data, path: path19, errorMaps, issueData } = params;
1263
- const fullPath = [...path19, ...issueData.path || []];
1262
+ const { data, path: path20, errorMaps, issueData } = params;
1263
+ const fullPath = [...path20, ...issueData.path || []];
1264
1264
  const fullIssue = {
1265
1265
  ...issueData,
1266
1266
  path: fullPath
@@ -1540,11 +1540,11 @@ var init_types = __esm({
1540
1540
  init_parseUtil();
1541
1541
  init_util();
1542
1542
  ParseInputLazyPath = class {
1543
- constructor(parent, value, path19, key) {
1543
+ constructor(parent, value, path20, key) {
1544
1544
  this._cachedPath = [];
1545
1545
  this.parent = parent;
1546
1546
  this.data = value;
1547
- this._path = path19;
1547
+ this._path = path20;
1548
1548
  this._key = key;
1549
1549
  }
1550
1550
  get path() {
@@ -4996,10 +4996,10 @@ function assignProp(target, prop, value) {
4996
4996
  configurable: true
4997
4997
  });
4998
4998
  }
4999
- function getElementAtPath(obj, path19) {
5000
- if (!path19)
4999
+ function getElementAtPath(obj, path20) {
5000
+ if (!path20)
5001
5001
  return obj;
5002
- return path19.reduce((acc, key) => acc?.[key], obj);
5002
+ return path20.reduce((acc, key) => acc?.[key], obj);
5003
5003
  }
5004
5004
  function promiseAllObject(promisesObj) {
5005
5005
  const keys = Object.keys(promisesObj);
@@ -5248,11 +5248,11 @@ function aborted(x, startIndex = 0) {
5248
5248
  }
5249
5249
  return false;
5250
5250
  }
5251
- function prefixIssues(path19, issues) {
5251
+ function prefixIssues(path20, issues) {
5252
5252
  return issues.map((iss) => {
5253
5253
  var _a;
5254
5254
  (_a = iss).path ?? (_a.path = []);
5255
- iss.path.unshift(path19);
5255
+ iss.path.unshift(path20);
5256
5256
  return iss;
5257
5257
  });
5258
5258
  }
@@ -17058,8 +17058,8 @@ var require_utils = __commonJS({
17058
17058
  }
17059
17059
  return ind;
17060
17060
  }
17061
- function removeDotSegments(path19) {
17062
- let input = path19;
17061
+ function removeDotSegments(path20) {
17062
+ let input = path20;
17063
17063
  const output = [];
17064
17064
  let nextSlash = -1;
17065
17065
  let len = 0;
@@ -17258,8 +17258,8 @@ var require_schemes = __commonJS({
17258
17258
  wsComponent.secure = void 0;
17259
17259
  }
17260
17260
  if (wsComponent.resourceName) {
17261
- const [path19, query] = wsComponent.resourceName.split("?");
17262
- wsComponent.path = path19 && path19 !== "/" ? path19 : void 0;
17261
+ const [path20, query] = wsComponent.resourceName.split("?");
17262
+ wsComponent.path = path20 && path20 !== "/" ? path20 : void 0;
17263
17263
  wsComponent.query = query;
17264
17264
  wsComponent.resourceName = void 0;
17265
17265
  }
@@ -20612,12 +20612,12 @@ var require_dist = __commonJS({
20612
20612
  throw new Error(`Unknown format "${name}"`);
20613
20613
  return f;
20614
20614
  };
20615
- function addFormats(ajv, list, fs17, exportName) {
20615
+ function addFormats(ajv, list, fs18, exportName) {
20616
20616
  var _a;
20617
20617
  var _b;
20618
20618
  (_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
20619
20619
  for (const f of list)
20620
- ajv.addFormat(f, fs17[f]);
20620
+ ajv.addFormat(f, fs18[f]);
20621
20621
  }
20622
20622
  module.exports = exports = formatsPlugin;
20623
20623
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -21729,8 +21729,8 @@ var require_parseUtil = __commonJS({
21729
21729
  var errors_js_1 = require_errors2();
21730
21730
  var en_js_1 = __importDefault(require_en());
21731
21731
  var makeIssue2 = (params) => {
21732
- const { data, path: path19, errorMaps, issueData } = params;
21733
- const fullPath = [...path19, ...issueData.path || []];
21732
+ const { data, path: path20, errorMaps, issueData } = params;
21733
+ const fullPath = [...path20, ...issueData.path || []];
21734
21734
  const fullIssue = {
21735
21735
  ...issueData,
21736
21736
  path: fullPath
@@ -21884,11 +21884,11 @@ var require_types2 = __commonJS({
21884
21884
  var parseUtil_js_1 = require_parseUtil();
21885
21885
  var util_js_1 = require_util2();
21886
21886
  var ParseInputLazyPath2 = class {
21887
- constructor(parent, value, path19, key) {
21887
+ constructor(parent, value, path20, key) {
21888
21888
  this._cachedPath = [];
21889
21889
  this.parent = parent;
21890
21890
  this.data = value;
21891
- this._path = path19;
21891
+ this._path = path20;
21892
21892
  this._key = key;
21893
21893
  }
21894
21894
  get path() {
@@ -26389,8 +26389,8 @@ var init_stdio2 = __esm({
26389
26389
  // src/constants.ts
26390
26390
  import { createRequire } from "node:module";
26391
26391
  function resolveVersion() {
26392
- if ("3.20.6") {
26393
- return "3.20.6";
26392
+ if ("3.21.0") {
26393
+ return "3.21.0";
26394
26394
  }
26395
26395
  try {
26396
26396
  const require2 = createRequire(import.meta.url);
@@ -27031,10 +27031,6 @@ var init_peer_registry = __esm({
27031
27031
  // src/services/agent-config.ts
27032
27032
  import os4 from "node:os";
27033
27033
  import path8 from "node:path";
27034
- function claudeConfigDir() {
27035
- const override = process.env.CLAUDE_CONFIG_DIR?.trim();
27036
- return override ? override : path8.join(os4.homedir(), ".claude");
27037
- }
27038
27034
  function codexHomeDir() {
27039
27035
  const override = process.env.CODEX_HOME?.trim();
27040
27036
  return override ? override : path8.join(os4.homedir(), ".codex");
@@ -27053,26 +27049,149 @@ var init_agent_config = __esm({
27053
27049
  }
27054
27050
  });
27055
27051
 
27056
- // src/services/cc-cli.ts
27057
- import { spawn } from "node:child_process";
27052
+ // src/services/agent-sessions.ts
27053
+ import crypto3 from "node:crypto";
27058
27054
  import fs7 from "node:fs/promises";
27055
+ import os5 from "node:os";
27059
27056
  import path9 from "node:path";
27060
- async function listCandidates(cwd) {
27057
+ function hashCwd(cwd) {
27058
+ return crypto3.createHash("sha256").update(path9.resolve(cwd)).digest("hex").slice(0, 16);
27059
+ }
27060
+ function agentSessionsDir() {
27061
+ return path9.join(os5.homedir(), ".cogent", "agent-sessions");
27062
+ }
27063
+ function agentSessionPath(cwd, platform) {
27064
+ return path9.join(agentSessionsDir(), `${hashCwd(cwd)}.${platform}.json`);
27065
+ }
27066
+ async function readAgentSession(cwd, platform) {
27061
27067
  try {
27062
- const escapedCwd = cwd.replace(/[^a-zA-Z0-9-]/g, "-");
27063
- const projectDir = path9.join(claudeConfigDir(), "projects", escapedCwd);
27064
- const entries = await fs7.readdir(projectDir);
27065
- const jsonlFiles = entries.filter((f) => f.endsWith(".jsonl"));
27066
- return await Promise.all(
27067
- jsonlFiles.map(async (f) => ({
27068
- sessionId: f.replace(".jsonl", ""),
27069
- mtimeMs: (await fs7.stat(path9.join(projectDir, f))).mtimeMs
27070
- }))
27068
+ const raw = await fs7.readFile(agentSessionPath(cwd, platform), "utf-8");
27069
+ const rec = JSON.parse(raw);
27070
+ if (!rec?.sessionId || !rec?.transcriptPath) return null;
27071
+ return rec;
27072
+ } catch {
27073
+ return null;
27074
+ }
27075
+ }
27076
+ async function learnedRoots(platform) {
27077
+ try {
27078
+ const dir = agentSessionsDir();
27079
+ const files = (await fs7.readdir(dir)).filter(
27080
+ (f) => f.endsWith(`.${platform}.json`)
27081
+ );
27082
+ const recs = await Promise.all(
27083
+ files.map(async (f) => {
27084
+ try {
27085
+ return JSON.parse(
27086
+ await fs7.readFile(path9.join(dir, f), "utf-8")
27087
+ );
27088
+ } catch {
27089
+ return null;
27090
+ }
27091
+ })
27071
27092
  );
27093
+ return [
27094
+ ...new Set(
27095
+ recs.filter((r) => Boolean(r?.root)).sort((a, b) => a.updatedAt < b.updatedAt ? 1 : -1).map((r) => r.root)
27096
+ )
27097
+ ];
27072
27098
  } catch {
27073
27099
  return [];
27074
27100
  }
27075
27101
  }
27102
+ var init_agent_sessions = __esm({
27103
+ "src/services/agent-sessions.ts"() {
27104
+ "use strict";
27105
+ }
27106
+ });
27107
+
27108
+ // src/services/cc-cli.ts
27109
+ import { spawn } from "node:child_process";
27110
+ import fs8 from "node:fs/promises";
27111
+ import os6 from "node:os";
27112
+ import path10 from "node:path";
27113
+ async function projectDirsFor(cwd) {
27114
+ const [roots, forms] = await Promise.all([
27115
+ claudeConfigRoots(),
27116
+ cwdForms(cwd)
27117
+ ]);
27118
+ const dirs = roots.flatMap(
27119
+ (root) => forms.map(
27120
+ (f) => path10.join(root, "projects", f.replace(/[^a-zA-Z0-9-]/g, "-"))
27121
+ )
27122
+ );
27123
+ return [...new Set(dirs)];
27124
+ }
27125
+ async function cwdForms(cwd) {
27126
+ const resolved = path10.resolve(cwd);
27127
+ const forms = /* @__PURE__ */ new Set([resolved]);
27128
+ try {
27129
+ forms.add(await fs8.realpath(resolved));
27130
+ } catch {
27131
+ }
27132
+ return [...forms];
27133
+ }
27134
+ async function claudeConfigRoots() {
27135
+ const roots = [];
27136
+ const env = process.env.CLAUDE_CONFIG_DIR?.trim();
27137
+ if (env) roots.push(env);
27138
+ roots.push(...await learnedRoots("cc"));
27139
+ roots.push(path10.join(os6.homedir(), ".claude"));
27140
+ roots.push(path10.join(os6.homedir(), ".config", "claude"));
27141
+ return [...new Set(roots.map((r) => path10.resolve(r)))];
27142
+ }
27143
+ async function recordedCandidate(cwd) {
27144
+ const rec = await readAgentSession(cwd, "cc");
27145
+ if (!rec) return null;
27146
+ try {
27147
+ const st = await fs8.stat(rec.transcriptPath);
27148
+ return { sessionId: rec.sessionId, mtimeMs: st.mtimeMs };
27149
+ } catch {
27150
+ return null;
27151
+ }
27152
+ }
27153
+ async function transcriptBaseSummary() {
27154
+ const roots = await claudeConfigRoots();
27155
+ const parts = await Promise.all(
27156
+ roots.map(async (root) => {
27157
+ const base = path10.join(root, "projects");
27158
+ try {
27159
+ return `${base} [${(await fs8.readdir(base)).length} project dirs]`;
27160
+ } catch {
27161
+ return `${base} [absent]`;
27162
+ }
27163
+ })
27164
+ );
27165
+ return parts.join(", ");
27166
+ }
27167
+ async function listCandidates(cwd) {
27168
+ const dirs = await projectDirsFor(cwd);
27169
+ const perDir = await Promise.all(
27170
+ dirs.map(async (projectDir) => {
27171
+ try {
27172
+ const entries = await fs8.readdir(projectDir);
27173
+ return await Promise.all(
27174
+ entries.filter((f) => f.endsWith(".jsonl")).map(async (f) => ({
27175
+ sessionId: f.replace(".jsonl", ""),
27176
+ mtimeMs: (await fs8.stat(path10.join(projectDir, f))).mtimeMs
27177
+ }))
27178
+ );
27179
+ } catch {
27180
+ return [];
27181
+ }
27182
+ })
27183
+ );
27184
+ const byId = /* @__PURE__ */ new Map();
27185
+ for (const c2 of perDir.flat()) {
27186
+ const prev = byId.get(c2.sessionId);
27187
+ if (!prev || c2.mtimeMs > prev.mtimeMs) byId.set(c2.sessionId, c2);
27188
+ }
27189
+ const recorded = await recordedCandidate(cwd);
27190
+ if (recorded && !byId.has(recorded.sessionId)) {
27191
+ byId.set(recorded.sessionId, recorded);
27192
+ }
27193
+ return [...byId.values()];
27194
+ }
27076
27195
  async function detectCurrentSession(cwd) {
27077
27196
  const candidates = await listCandidates(cwd);
27078
27197
  if (candidates.length === 0) return null;
@@ -27080,19 +27199,20 @@ async function detectCurrentSession(cwd) {
27080
27199
  return candidates[0].sessionId;
27081
27200
  }
27082
27201
  async function validateSession(sessionId, cwd) {
27083
- const projectHash = cwd.replace(/[^a-zA-Z0-9-]/g, "-");
27084
- const sessionPath = path9.join(
27085
- claudeConfigDir(),
27086
- "projects",
27087
- projectHash,
27088
- `${sessionId}.jsonl`
27202
+ const recorded = await recordedCandidate(cwd);
27203
+ if (recorded?.sessionId === sessionId) return true;
27204
+ const dirs = await projectDirsFor(cwd);
27205
+ const hits = await Promise.all(
27206
+ dirs.map(async (dir) => {
27207
+ try {
27208
+ await fs8.access(path10.join(dir, `${sessionId}.jsonl`));
27209
+ return true;
27210
+ } catch {
27211
+ return false;
27212
+ }
27213
+ })
27089
27214
  );
27090
- try {
27091
- await fs7.access(sessionPath);
27092
- return true;
27093
- } catch {
27094
- return false;
27095
- }
27215
+ return hits.some(Boolean);
27096
27216
  }
27097
27217
  function execClaude(sessionId, message, cwd, timeoutMs) {
27098
27218
  return new Promise((resolve) => {
@@ -27246,15 +27366,16 @@ var init_cc_cli = __esm({
27246
27366
  "use strict";
27247
27367
  init_config();
27248
27368
  init_agent_config();
27369
+ init_agent_sessions();
27249
27370
  }
27250
27371
  });
27251
27372
 
27252
27373
  // src/services/codex-preflight.ts
27253
27374
  import { execFile as execFile2 } from "node:child_process";
27254
27375
  import { promisify as promisify2 } from "node:util";
27255
- import fs8 from "node:fs/promises";
27376
+ import fs9 from "node:fs/promises";
27256
27377
  import { join } from "node:path";
27257
- import os5 from "node:os";
27378
+ import os7 from "node:os";
27258
27379
  function analyzeCodexHelp(helpText) {
27259
27380
  const checked = EXPECTED_CODEX_RESUME_FLAGS.map((f) => f.flag);
27260
27381
  const missing = EXPECTED_CODEX_RESUME_FLAGS.filter(
@@ -27310,7 +27431,7 @@ function classifyUnshareError(err) {
27310
27431
  }
27311
27432
  async function readProc(p) {
27312
27433
  try {
27313
- return (await fs8.readFile(p, "utf8")).trim();
27434
+ return (await fs9.readFile(p, "utf8")).trim();
27314
27435
  } catch {
27315
27436
  return null;
27316
27437
  }
@@ -27363,14 +27484,14 @@ function detectCodexCogentServerCollision(configTomlText) {
27363
27484
  return /^[ \t]*\[mcp_servers\.cogent(\.[^\]]+)?\]/m.test(configTomlText);
27364
27485
  }
27365
27486
  function codexConfigPath(codexHomeDir2) {
27366
- const home = codexHomeDir2 || process.env.CODEX_HOME || join(os5.homedir(), ".codex");
27487
+ const home = codexHomeDir2 || process.env.CODEX_HOME || join(os7.homedir(), ".codex");
27367
27488
  return join(home, "config.toml");
27368
27489
  }
27369
27490
  async function preflightCodexServerCollision(codexHomeDir2) {
27370
27491
  const cfgPath = codexConfigPath(codexHomeDir2);
27371
27492
  let text;
27372
27493
  try {
27373
- text = await fs8.readFile(cfgPath, "utf8");
27494
+ text = await fs9.readFile(cfgPath, "utf8");
27374
27495
  } catch {
27375
27496
  return false;
27376
27497
  }
@@ -27399,22 +27520,22 @@ var init_codex_preflight = __esm({
27399
27520
  });
27400
27521
 
27401
27522
  // src/services/health-check.ts
27402
- import fs9 from "node:fs/promises";
27403
- import path10 from "node:path";
27523
+ import fs10 from "node:fs/promises";
27524
+ import path11 from "node:path";
27404
27525
  import { execFile as execFile3 } from "node:child_process";
27405
27526
  function getStatePath2() {
27406
- return path10.join(getConfig().COGENT_STATE_PATH, "cogent-state.json");
27527
+ return path11.join(getConfig().COGENT_STATE_PATH, "cogent-state.json");
27407
27528
  }
27408
27529
  async function checkStateFile() {
27409
27530
  const statePath = getStatePath2();
27410
- const dir = path10.dirname(statePath);
27531
+ const dir = path11.dirname(statePath);
27411
27532
  try {
27412
- await fs9.access(dir, fs9.constants.R_OK | fs9.constants.W_OK);
27533
+ await fs10.access(dir, fs10.constants.R_OK | fs10.constants.W_OK);
27413
27534
  } catch {
27414
27535
  return { ok: false, message: `State directory not accessible: ${dir}` };
27415
27536
  }
27416
27537
  try {
27417
- const raw = await fs9.readFile(statePath, "utf-8");
27538
+ const raw = await fs10.readFile(statePath, "utf-8");
27418
27539
  JSON.parse(raw);
27419
27540
  return { ok: true, message: "State file readable and valid JSON" };
27420
27541
  } catch (err) {
@@ -27430,9 +27551,9 @@ async function checkStateFile() {
27430
27551
  async function checkLockMechanism() {
27431
27552
  const healthLockPath = getStatePath2() + ".health-lock";
27432
27553
  try {
27433
- await fs9.writeFile(healthLockPath, String(process.pid), { flag: "wx" });
27554
+ await fs10.writeFile(healthLockPath, String(process.pid), { flag: "wx" });
27434
27555
  try {
27435
- await fs9.unlink(healthLockPath);
27556
+ await fs10.unlink(healthLockPath);
27436
27557
  } catch {
27437
27558
  }
27438
27559
  return { ok: true, message: "Lock acquire/release cycle succeeded" };
@@ -27485,7 +27606,7 @@ async function checkHealth() {
27485
27606
  return {
27486
27607
  healthy,
27487
27608
  mcpServerVersion: SERVER_VERSION,
27488
- statePath: path10.join(config2.COGENT_STATE_PATH, "cogent-state.json"),
27609
+ statePath: path11.join(config2.COGENT_STATE_PATH, "cogent-state.json"),
27489
27610
  claudePath: config2.COGENT_CLAUDE_PATH,
27490
27611
  checks,
27491
27612
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
@@ -27624,7 +27745,7 @@ var init_http_backend = __esm({
27624
27745
  * in cloud mode we ignore it and use this.sessionId (the cloud session).
27625
27746
  */
27626
27747
  async registerPeer(peerId, _sessionId, cwd, label, clientVersion, mode, _channelSessionId, capabilities, workspaceId, threadId) {
27627
- const path19 = PATHS.peers.replace(":sessionId", this.sessionId);
27748
+ const path20 = PATHS.peers.replace(":sessionId", this.sessionId);
27628
27749
  const body = {
27629
27750
  peerId,
27630
27751
  cwd,
@@ -27652,7 +27773,7 @@ var init_http_backend = __esm({
27652
27773
  body.role = roleCap.slice("role:".length);
27653
27774
  }
27654
27775
  }
27655
- return this.http.post(path19, body);
27776
+ return this.http.post(path20, body);
27656
27777
  }
27657
27778
  /**
27658
27779
  * Deregister a peer from the cloud session.
@@ -27664,9 +27785,9 @@ var init_http_backend = __esm({
27664
27785
  * local mail creds. A 404 (peer not found) resolves to `{ removed: false, ... }`, not a throw.
27665
27786
  */
27666
27787
  async deregisterPeer(peerId) {
27667
- const path19 = PATHS.peer.replace(":sessionId", this.sessionId).replace(":peerId", peerId);
27788
+ const path20 = PATHS.peer.replace(":sessionId", this.sessionId).replace(":peerId", peerId);
27668
27789
  try {
27669
- const headers = await this.http.delete(path19, {});
27790
+ const headers = await this.http.delete(path20, {});
27670
27791
  const mailboxDeprovisioned = headers.get(MAILBOX_DEPROVISIONED_HEADER) === "true";
27671
27792
  return { removed: true, mailboxDeprovisioned };
27672
27793
  } catch {
@@ -27687,8 +27808,8 @@ var init_http_backend = __esm({
27687
27808
  * GET /api/sessions/:sessionId/peers
27688
27809
  */
27689
27810
  async listPeers() {
27690
- const path19 = PATHS.peers.replace(":sessionId", this.sessionId);
27691
- const result = await this.http.get(path19);
27811
+ const path20 = PATHS.peers.replace(":sessionId", this.sessionId);
27812
+ const result = await this.http.get(path20);
27692
27813
  return result.peers;
27693
27814
  }
27694
27815
  /**
@@ -27696,8 +27817,8 @@ var init_http_backend = __esm({
27696
27817
  * Calls the lightweight heartbeat endpoint on the cloud relay server.
27697
27818
  */
27698
27819
  async updateLastSeen(peerId) {
27699
- const path19 = PATHS.heartbeat.replace(":sessionId", this.sessionId);
27700
- await this.http.post(path19, { peerId });
27820
+ const path20 = PATHS.heartbeat.replace(":sessionId", this.sessionId);
27821
+ await this.http.post(path20, { peerId });
27701
27822
  }
27702
27823
  /**
27703
27824
  * Record a message in the cloud session.
@@ -27708,7 +27829,7 @@ var init_http_backend = __esm({
27708
27829
  * the input record to construct a full MessageRecord.
27709
27830
  */
27710
27831
  async recordMessage(record2) {
27711
- const path19 = PATHS.messages.replace(":sessionId", this.sessionId);
27832
+ const path20 = PATHS.messages.replace(":sessionId", this.sessionId);
27712
27833
  const body = {
27713
27834
  fromPeerId: record2.fromPeerId,
27714
27835
  toPeerId: record2.toPeerId,
@@ -27720,7 +27841,7 @@ var init_http_backend = __esm({
27720
27841
  if (record2.attachments && record2.attachments.length > 0) {
27721
27842
  body.attachments = record2.attachments;
27722
27843
  }
27723
- const resp = await this.http.post(path19, body);
27844
+ const resp = await this.http.post(path20, body);
27724
27845
  return {
27725
27846
  ...record2,
27726
27847
  id: resp.id,
@@ -27734,7 +27855,7 @@ var init_http_backend = __esm({
27734
27855
  * Supports optional peerId filter and limit (default 300).
27735
27856
  */
27736
27857
  async getHistory(peerId, limit, includeRelayEchoes, metadataOnly, dedupInferredEchoes) {
27737
- const path19 = PATHS.messages.replace(":sessionId", this.sessionId);
27858
+ const path20 = PATHS.messages.replace(":sessionId", this.sessionId);
27738
27859
  const query = {};
27739
27860
  if (peerId) {
27740
27861
  query.peerId = peerId;
@@ -27749,7 +27870,7 @@ var init_http_backend = __esm({
27749
27870
  if (dedupInferredEchoes) {
27750
27871
  query.dedupInferredEchoes = "true";
27751
27872
  }
27752
- const result = await this.http.get(path19, query);
27873
+ const result = await this.http.get(path20, query);
27753
27874
  return result.messages;
27754
27875
  }
27755
27876
  /**
@@ -27760,12 +27881,12 @@ var init_http_backend = __esm({
27760
27881
  * so that get-history shows the actual response (not null).
27761
27882
  */
27762
27883
  async updateMessageResponse(messageId, response, durationMs, pending) {
27763
- const path19 = PATHS.message.replace(":sessionId", this.sessionId).replace(":messageId", messageId);
27884
+ const path20 = PATHS.message.replace(":sessionId", this.sessionId).replace(":messageId", messageId);
27764
27885
  const body = { response, durationMs };
27765
27886
  if (pending === true) {
27766
27887
  body.pending = true;
27767
27888
  }
27768
- await this.http.patch(path19, body);
27889
+ await this.http.patch(path20, body);
27769
27890
  }
27770
27891
  /**
27771
27892
  * Validate a session.
@@ -27907,8 +28028,8 @@ var init_http_client = __esm({
27907
28028
  * Perform an authenticated GET request.
27908
28029
  * Appends query parameters to the URL if provided.
27909
28030
  */
27910
- async get(path19, query) {
27911
- const url = new URL(path19, this.baseUrl);
28031
+ async get(path20, query) {
28032
+ const url = new URL(path20, this.baseUrl);
27912
28033
  if (query) {
27913
28034
  for (const [k, v] of Object.entries(query)) {
27914
28035
  url.searchParams.set(k, v);
@@ -27923,8 +28044,8 @@ var init_http_client = __esm({
27923
28044
  /**
27924
28045
  * Perform an authenticated POST request with a JSON body.
27925
28046
  */
27926
- async post(path19, body) {
27927
- const url = new URL(path19, this.baseUrl);
28047
+ async post(path20, body) {
28048
+ const url = new URL(path20, this.baseUrl);
27928
28049
  const resp = await this.fetchWithTimeout(url, {
27929
28050
  method: "POST",
27930
28051
  headers: this.headers(),
@@ -27942,8 +28063,8 @@ var init_http_client = __esm({
27942
28063
  * Perform an authenticated PATCH request with a JSON body.
27943
28064
  * Used to update existing resources (e.g., message response fields).
27944
28065
  */
27945
- async patch(path19, body) {
27946
- const url = new URL(path19, this.baseUrl);
28066
+ async patch(path20, body) {
28067
+ const url = new URL(path20, this.baseUrl);
27947
28068
  const resp = await this.fetchWithTimeout(url, {
27948
28069
  method: "PATCH",
27949
28070
  headers: this.headers(),
@@ -27968,8 +28089,8 @@ var init_http_client = __esm({
27968
28089
  * "Malformed JSON in request body" 400 from cogent-server <=3.1.2 when
27969
28090
  * any client (including third-party tools) DELETEd a peer without a body.
27970
28091
  */
27971
- async delete(path19, body) {
27972
- const url = new URL(path19, this.baseUrl);
28092
+ async delete(path20, body) {
28093
+ const url = new URL(path20, this.baseUrl);
27973
28094
  const headers = {
27974
28095
  "Authorization": `Bearer ${this.token}`
27975
28096
  };
@@ -32152,14 +32273,14 @@ var init_ws_client = __esm({
32152
32273
  if (this.pollTimer) return;
32153
32274
  const poll = async () => {
32154
32275
  try {
32155
- const path19 = `/api/sessions/${this.opts.sessionId}/poll`;
32276
+ const path20 = `/api/sessions/${this.opts.sessionId}/poll`;
32156
32277
  const query = {
32157
32278
  peerId: this.opts.peerId
32158
32279
  };
32159
32280
  if (this.lastMessageId) {
32160
32281
  query.lastMessageId = this.lastMessageId;
32161
32282
  }
32162
- const result = await this.opts.http.get(path19, query);
32283
+ const result = await this.opts.http.get(path20, query);
32163
32284
  if (result.messages && result.messages.length > 0) {
32164
32285
  this.opts.onMessages(result.messages);
32165
32286
  this.lastMessageId = result.messages[result.messages.length - 1].id;
@@ -32216,9 +32337,9 @@ var init_cloud = __esm({
32216
32337
 
32217
32338
  // src/services/codex-cli.ts
32218
32339
  import { spawn as spawn2 } from "node:child_process";
32219
- import fs10 from "node:fs/promises";
32220
- import os6 from "node:os";
32221
- import path11 from "node:path";
32340
+ import fs11 from "node:fs/promises";
32341
+ import os8 from "node:os";
32342
+ import path12 from "node:path";
32222
32343
  import { randomUUID } from "node:crypto";
32223
32344
  import { createReadStream } from "node:fs";
32224
32345
  import { createInterface as createInterface2 } from "node:readline";
@@ -32246,7 +32367,7 @@ function execCodex(sessionId, message, cwd, timeoutMs) {
32246
32367
  const config2 = getConfig();
32247
32368
  const effectiveTimeout = timeoutMs ?? config2.COGENT_TIMEOUT_MS;
32248
32369
  const truncated = config2.COGENT_CHAR_LIMIT > 0 && message.length > config2.COGENT_CHAR_LIMIT ? message.slice(0, config2.COGENT_CHAR_LIMIT) + "\n...[truncated]" : message;
32249
- const lastMsgFile = path11.join(os6.tmpdir(), `cogent-codex-${randomUUID()}.txt`);
32370
+ const lastMsgFile = path12.join(os8.tmpdir(), `cogent-codex-${randomUUID()}.txt`);
32250
32371
  const args = [
32251
32372
  "exec",
32252
32373
  "resume",
@@ -32274,7 +32395,7 @@ function execCodex(sessionId, message, cwd, timeoutMs) {
32274
32395
  resolve(result);
32275
32396
  }
32276
32397
  };
32277
- const cleanupFile = () => fs10.rm(lastMsgFile, { force: true }).catch(() => {
32398
+ const cleanupFile = () => fs11.rm(lastMsgFile, { force: true }).catch(() => {
32278
32399
  });
32279
32400
  const timer = setTimeout(async () => {
32280
32401
  killed = true;
@@ -32325,7 +32446,7 @@ function execCodex(sessionId, message, cwd, timeoutMs) {
32325
32446
  }
32326
32447
  let fileMessage = "";
32327
32448
  try {
32328
- fileMessage = await fs10.readFile(lastMsgFile, "utf8");
32449
+ fileMessage = await fs11.readFile(lastMsgFile, "utf8");
32329
32450
  } catch {
32330
32451
  fileMessage = "";
32331
32452
  }
@@ -32346,12 +32467,12 @@ async function listRolloutFiles(root) {
32346
32467
  async function walk(dir) {
32347
32468
  let entries;
32348
32469
  try {
32349
- entries = await fs10.readdir(dir, { withFileTypes: true });
32470
+ entries = await fs11.readdir(dir, { withFileTypes: true });
32350
32471
  } catch {
32351
32472
  return;
32352
32473
  }
32353
32474
  for (const e of entries) {
32354
- const full = path11.join(dir, e.name);
32475
+ const full = path12.join(dir, e.name);
32355
32476
  if (e.isDirectory()) await walk(full);
32356
32477
  else if (e.isFile() && e.name.endsWith(".jsonl")) out.push(full);
32357
32478
  }
@@ -32383,19 +32504,19 @@ async function readSessionMeta(file) {
32383
32504
  }
32384
32505
  }
32385
32506
  function codexSessionsRoot() {
32386
- return path11.join(codexHomeDir(), "sessions");
32507
+ return path12.join(codexHomeDir(), "sessions");
32387
32508
  }
32388
32509
  async function cwdCanonicals(cwd) {
32389
- const resolved = path11.resolve(cwd);
32510
+ const resolved = path12.resolve(cwd);
32390
32511
  const forms = /* @__PURE__ */ new Set([resolved]);
32391
32512
  try {
32392
- forms.add(await fs10.realpath(resolved));
32513
+ forms.add(await fs11.realpath(resolved));
32393
32514
  } catch {
32394
32515
  }
32395
32516
  return forms;
32396
32517
  }
32397
32518
  function metaCwdMatches(metaCwd, forms) {
32398
- return forms.has(path11.resolve(metaCwd));
32519
+ return forms.has(path12.resolve(metaCwd));
32399
32520
  }
32400
32521
  async function detectCurrentCodexSession(cwd) {
32401
32522
  try {
@@ -32403,7 +32524,7 @@ async function detectCurrentCodexSession(cwd) {
32403
32524
  const files = await listRolloutFiles(codexSessionsRoot());
32404
32525
  const withStats = await Promise.all(
32405
32526
  files.map(async (f) => {
32406
- const stat = await fs10.stat(f);
32527
+ const stat = await fs11.stat(f);
32407
32528
  return { file: f, mtimeMs: stat.mtimeMs };
32408
32529
  })
32409
32530
  );
@@ -32422,7 +32543,7 @@ async function listCodexCandidates(cwd) {
32422
32543
  const forms = await cwdCanonicals(cwd);
32423
32544
  const files = await listRolloutFiles(codexSessionsRoot());
32424
32545
  const withStats = await Promise.all(
32425
- files.map(async (f) => ({ file: f, mtimeMs: (await fs10.stat(f)).mtimeMs }))
32546
+ files.map(async (f) => ({ file: f, mtimeMs: (await fs11.stat(f)).mtimeMs }))
32426
32547
  );
32427
32548
  const bySession = /* @__PURE__ */ new Map();
32428
32549
  for (const { file, mtimeMs } of withStats) {
@@ -32462,11 +32583,11 @@ var init_codex_cli = __esm({
32462
32583
  });
32463
32584
 
32464
32585
  // src/services/codex-app-server.ts
32465
- import path12 from "node:path";
32466
- import fs11 from "node:fs/promises";
32586
+ import path13 from "node:path";
32587
+ import fs12 from "node:fs/promises";
32467
32588
  import { spawn as spawn3, spawnSync } from "node:child_process";
32468
32589
  function appServerSocketPath(codexHome = codexHomeDir()) {
32469
- return path12.join(codexHome, "app-server-control", "app-server-control.sock");
32590
+ return path13.join(codexHome, "app-server-control", "app-server-control.sock");
32470
32591
  }
32471
32592
  function rpcUrl(sock) {
32472
32593
  return `ws+unix://${sock}:/rpc`;
@@ -32707,7 +32828,7 @@ var init_codex_app_server = __esm({
32707
32828
  });
32708
32829
  defaultSocketExists = async (p) => {
32709
32830
  try {
32710
- await fs11.stat(p);
32831
+ await fs12.stat(p);
32711
32832
  return true;
32712
32833
  } catch {
32713
32834
  return false;
@@ -32834,6 +32955,23 @@ function listCandidatesFor(platform, cwd) {
32834
32955
  return listCandidates(cwd);
32835
32956
  }
32836
32957
  }
32958
+ async function reportedSessionFor(platform, cwd) {
32959
+ if (platform !== "cc") return null;
32960
+ try {
32961
+ return (await recordedCandidate(cwd))?.sessionId ?? null;
32962
+ } catch {
32963
+ return null;
32964
+ }
32965
+ }
32966
+ function probePathsFor(platform, cwd) {
32967
+ switch (platform) {
32968
+ case "codex":
32969
+ return Promise.resolve([codexSessionsRoot()]);
32970
+ case "cc":
32971
+ default:
32972
+ return projectDirsFor(cwd);
32973
+ }
32974
+ }
32837
32975
  function validateSessionFor(platform, sessionId, cwd) {
32838
32976
  switch (platform) {
32839
32977
  case "codex":
@@ -32905,12 +33043,31 @@ function decideResolution(candidates, pinnedSessionId, pinnedExists, marginMs) {
32905
33043
  };
32906
33044
  }
32907
33045
  async function resolveSession(platform, cwd, pinnedSessionId, marginMs) {
32908
- const [candidates, pinnedExists] = await Promise.all([
33046
+ const [candidates, pinnedExists, reported] = await Promise.all([
32909
33047
  listCandidatesFor(platform, cwd),
32910
- pinnedSessionId ? validateSessionFor(platform, pinnedSessionId, cwd) : Promise.resolve(false)
33048
+ pinnedSessionId ? validateSessionFor(platform, pinnedSessionId, cwd) : Promise.resolve(false),
33049
+ // Layer 1 is an ENHANCEMENT over discovery, never a dependency of it: if the
33050
+ // learned-record lookup is unavailable or throws, resolution must still run
33051
+ // exactly as it did before this layer existed.
33052
+ Promise.resolve().then(() => reportedSessionFor(platform, cwd)).catch(() => null)
32911
33053
  ]);
32912
33054
  const margin = marginMs ?? getConfig().COGENT_RESOLVER_AMBIGUOUS_MARGIN_MS;
32913
- return decideResolution(candidates, pinnedSessionId, pinnedExists, margin);
33055
+ const effectivePin = pinnedExists ? pinnedSessionId : reported ?? pinnedSessionId;
33056
+ const effectiveExists = pinnedExists || reported !== null && reported === effectivePin;
33057
+ const res = decideResolution(candidates, effectivePin, effectiveExists, margin);
33058
+ if (res.candidateCount === 0) {
33059
+ try {
33060
+ const probedPaths = await probePathsFor(platform, cwd);
33061
+ if (probedPaths.length) {
33062
+ res.probedPaths = probedPaths;
33063
+ if (res.fallbackReason) {
33064
+ res.fallbackReason = `${res.fallbackReason} (cwd=${cwd}; scanned ${probedPaths.join(", ")})`;
33065
+ }
33066
+ }
33067
+ } catch {
33068
+ }
33069
+ }
33070
+ return res;
32914
33071
  }
32915
33072
  var init_session_resolver = __esm({
32916
33073
  "src/services/session-resolver.ts"() {
@@ -32921,15 +33078,15 @@ var init_session_resolver = __esm({
32921
33078
  });
32922
33079
 
32923
33080
  // src/services/wake-inflight.ts
32924
- import crypto3 from "node:crypto";
32925
- import fs12 from "node:fs";
32926
- import os7 from "node:os";
32927
- import path13 from "node:path";
32928
- function hashCwd(cwd) {
32929
- return crypto3.createHash("sha256").update(path13.resolve(cwd)).digest("hex").slice(0, 16);
33081
+ import crypto4 from "node:crypto";
33082
+ import fs13 from "node:fs";
33083
+ import os9 from "node:os";
33084
+ import path14 from "node:path";
33085
+ function hashCwd2(cwd) {
33086
+ return crypto4.createHash("sha256").update(path14.resolve(cwd)).digest("hex").slice(0, 16);
32930
33087
  }
32931
33088
  function wakeInflightPath(peerId, cwd = process.cwd()) {
32932
- return path13.join(os7.homedir(), ".cogent", "wake-inflight", `${hashCwd(cwd)}.${safe(peerId)}.json`);
33089
+ return path14.join(os9.homedir(), ".cogent", "wake-inflight", `${hashCwd2(cwd)}.${safe(peerId)}.json`);
32933
33090
  }
32934
33091
  function ttlMs() {
32935
33092
  let timeout = 3e5;
@@ -32942,17 +33099,17 @@ function ttlMs() {
32942
33099
  }
32943
33100
  function readFileSafe(p) {
32944
33101
  try {
32945
- const parsed = JSON.parse(fs12.readFileSync(p, "utf-8"));
33102
+ const parsed = JSON.parse(fs13.readFileSync(p, "utf-8"));
32946
33103
  return parsed && typeof parsed === "object" && parsed.messages ? parsed : { messages: {} };
32947
33104
  } catch {
32948
33105
  return { messages: {} };
32949
33106
  }
32950
33107
  }
32951
33108
  function writeAtomic(p, data) {
32952
- fs12.mkdirSync(path13.dirname(p), { recursive: true });
33109
+ fs13.mkdirSync(path14.dirname(p), { recursive: true });
32953
33110
  const tmp = `${p}.${process.pid}.tmp`;
32954
- fs12.writeFileSync(tmp, JSON.stringify(data, null, 2) + "\n", "utf-8");
32955
- fs12.renameSync(tmp, p);
33111
+ fs13.writeFileSync(tmp, JSON.stringify(data, null, 2) + "\n", "utf-8");
33112
+ fs13.renameSync(tmp, p);
32956
33113
  }
32957
33114
  function prune(f, now) {
32958
33115
  for (const [id, rec] of Object.entries(f.messages)) {
@@ -34101,15 +34258,15 @@ __export(startup_exports, {
34101
34258
  runStartup: () => runStartup,
34102
34259
  triggerReRegistration: () => triggerReRegistration
34103
34260
  });
34104
- import os8 from "node:os";
34105
- import path14 from "node:path";
34106
- import fs13 from "node:fs/promises";
34261
+ import os10 from "node:os";
34262
+ import path15 from "node:path";
34263
+ import fs14 from "node:fs/promises";
34107
34264
  import readline2 from "node:readline";
34108
34265
  import { execFile as execFile5 } from "node:child_process";
34109
34266
  import { promisify as promisify4 } from "node:util";
34110
34267
  async function loadPersistedConfig() {
34111
34268
  try {
34112
- const raw = await fs13.readFile(PERSIST_PATH, "utf-8");
34269
+ const raw = await fs14.readFile(PERSIST_PATH, "utf-8");
34113
34270
  return JSON.parse(raw);
34114
34271
  } catch {
34115
34272
  return {};
@@ -34117,7 +34274,7 @@ async function loadPersistedConfig() {
34117
34274
  }
34118
34275
  async function savePersistedConfig(config2) {
34119
34276
  try {
34120
- await fs13.writeFile(PERSIST_PATH, JSON.stringify(config2, null, 2) + "\n", "utf-8");
34277
+ await fs14.writeFile(PERSIST_PATH, JSON.stringify(config2, null, 2) + "\n", "utf-8");
34121
34278
  } catch (err) {
34122
34279
  const msg = err instanceof Error ? err.message : String(err);
34123
34280
  logger.warn(`Could not save config to ${PERSIST_PATH}: ${msg}`);
@@ -34152,11 +34309,11 @@ First run detected. Where should cogent-bridge store its data?
34152
34309
  });
34153
34310
  }
34154
34311
  async function validateStateDir(statePath) {
34155
- await fs13.mkdir(statePath, { recursive: true });
34156
- const testFile = path14.join(statePath, ".write-test");
34312
+ await fs14.mkdir(statePath, { recursive: true });
34313
+ const testFile = path15.join(statePath, ".write-test");
34157
34314
  try {
34158
- await fs13.writeFile(testFile, "test", "utf-8");
34159
- await fs13.unlink(testFile);
34315
+ await fs14.writeFile(testFile, "test", "utf-8");
34316
+ await fs14.unlink(testFile);
34160
34317
  } catch {
34161
34318
  throw new BridgeError(
34162
34319
  "STARTUP_FAILED" /* STARTUP_FAILED */,
@@ -34302,10 +34459,10 @@ async function runStartup() {
34302
34459
  if (envStatePath) {
34303
34460
  statePath = envStatePath;
34304
34461
  } else {
34305
- const defaultPath = path14.join(os8.homedir(), ".cogent");
34462
+ const defaultPath = path15.join(os10.homedir(), ".cogent");
34306
34463
  statePath = await firstRunPrompt(defaultPath);
34307
34464
  }
34308
- if (!envStatePath && statePath !== path14.join(os8.homedir(), ".cogent")) {
34465
+ if (!envStatePath && statePath !== path15.join(os10.homedir(), ".cogent")) {
34309
34466
  process.env.COGENT_STATE_PATH = statePath;
34310
34467
  } else if (!envStatePath) {
34311
34468
  process.env.COGENT_STATE_PATH = statePath;
@@ -34383,7 +34540,7 @@ async function runStartup() {
34383
34540
  }
34384
34541
  initLogger(
34385
34542
  config2.COGENT_LOG_LEVEL,
34386
- path14.join(config2.COGENT_STATE_PATH, "logs")
34543
+ path15.join(config2.COGENT_STATE_PATH, "logs")
34387
34544
  );
34388
34545
  if (isCloud && effectiveSessionId && effectiveToken) {
34389
34546
  cloudInbox = new MessageInbox();
@@ -34444,7 +34601,7 @@ var init_startup = __esm({
34444
34601
  init_auto_relay();
34445
34602
  UUID_V4_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
34446
34603
  execFileAsync3 = promisify4(execFile5);
34447
- PERSIST_PATH = path14.join(os8.homedir(), ".cogent-config.json");
34604
+ PERSIST_PATH = path15.join(os10.homedir(), ".cogent-config.json");
34448
34605
  legacyWarnEmitted = false;
34449
34606
  cloudWsClient = null;
34450
34607
  cloudInbox = null;
@@ -34454,13 +34611,13 @@ var init_startup = __esm({
34454
34611
  });
34455
34612
 
34456
34613
  // src/cloud/mail-credential-store.ts
34457
- import crypto4 from "node:crypto";
34458
- import fs14 from "node:fs/promises";
34459
- import path15 from "node:path";
34460
- import os9 from "node:os";
34614
+ import crypto5 from "node:crypto";
34615
+ import fs15 from "node:fs/promises";
34616
+ import path16 from "node:path";
34617
+ import os11 from "node:os";
34461
34618
  function defaultMailCredentialPath(cwd = process.cwd()) {
34462
- const hash = crypto4.createHash("sha256").update(path15.resolve(cwd)).digest("hex").slice(0, 16);
34463
- return path15.join(os9.homedir(), ".cogent", "mail-credentials", `${hash}.json`);
34619
+ const hash = crypto5.createHash("sha256").update(path16.resolve(cwd)).digest("hex").slice(0, 16);
34620
+ return path16.join(os11.homedir(), ".cogent", "mail-credentials", `${hash}.json`);
34464
34621
  }
34465
34622
  function resolveMailCredentialPath(credentialPath) {
34466
34623
  if (credentialPath) return credentialPath;
@@ -34471,16 +34628,16 @@ function resolveMailCredentialPath(credentialPath) {
34471
34628
  async function loadMailCredentials(credentialPath) {
34472
34629
  const filePath = resolveMailCredentialPath(credentialPath);
34473
34630
  try {
34474
- return JSON.parse(await fs14.readFile(filePath, "utf-8"));
34631
+ return JSON.parse(await fs15.readFile(filePath, "utf-8"));
34475
34632
  } catch {
34476
34633
  return null;
34477
34634
  }
34478
34635
  }
34479
34636
  async function saveMailCredentials(creds, credentialPath) {
34480
34637
  const filePath = resolveMailCredentialPath(credentialPath);
34481
- await fs14.mkdir(path15.dirname(filePath), { recursive: true, mode: 448 });
34482
- await fs14.writeFile(filePath, JSON.stringify(creds, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
34483
- await fs14.chmod(filePath, 384);
34638
+ await fs15.mkdir(path16.dirname(filePath), { recursive: true, mode: 448 });
34639
+ await fs15.writeFile(filePath, JSON.stringify(creds, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
34640
+ await fs15.chmod(filePath, 384);
34484
34641
  }
34485
34642
  async function persistProvisionedMailbox(mailbox, credentialPath) {
34486
34643
  if (!mailbox?.address || !mailbox.password) return false;
@@ -34501,7 +34658,7 @@ async function persistProvisionedMailbox(mailbox, credentialPath) {
34501
34658
  async function clearMailCredentials(credentialPath) {
34502
34659
  const filePath = resolveMailCredentialPath(credentialPath);
34503
34660
  try {
34504
- await fs14.unlink(filePath);
34661
+ await fs15.unlink(filePath);
34505
34662
  } catch (err) {
34506
34663
  if (err.code !== "ENOENT") throw err;
34507
34664
  }
@@ -34515,7 +34672,7 @@ var init_mail_credential_store = __esm({
34515
34672
  });
34516
34673
 
34517
34674
  // src/tools/register-peer.ts
34518
- import crypto5 from "node:crypto";
34675
+ import crypto6 from "node:crypto";
34519
34676
  function registerRegisterPeerTool(server) {
34520
34677
  server.registerTool(
34521
34678
  "cogent_register_peer",
@@ -34574,7 +34731,7 @@ function registerRegisterPeerTool(server) {
34574
34731
  }
34575
34732
  }
34576
34733
  if (!cloudSessionId) {
34577
- autoSecret = crypto5.randomBytes(16).toString("hex");
34734
+ autoSecret = crypto6.randomBytes(16).toString("hex");
34578
34735
  const resp = await fetch(
34579
34736
  `${endpoint}/api/sessions`,
34580
34737
  {
@@ -34680,6 +34837,19 @@ function registerRegisterPeerTool(server) {
34680
34837
  logger.info(
34681
34838
  `Register: session resolved ${resolution.decision}/${resolution.confidence} (${resolution.candidateCount} candidate[s]) -> ${localSessionId}`
34682
34839
  );
34840
+ const noLocalSession = resolution.candidateCount === 0;
34841
+ if (noLocalSession) {
34842
+ try {
34843
+ const base = getConfig().COGENT_PLATFORM === "cc" ? await transcriptBaseSummary() : "(codex: scans CODEX_HOME/sessions)";
34844
+ logger.warn(
34845
+ `Register: NO local ${getConfig().COGENT_PLATFORM} session found for cwd \u2014 auto-wake WILL be refused. cwd=${cwd}; scanned ${(resolution.probedPaths ?? []).join(", ") || "(unknown)"}; base ${base}. If the base is missing or empty, this agent's config dir is elsewhere \u2014 set CLAUDE_CONFIG_DIR / CODEX_HOME so the BRIDGE process sees it too. If the base has project dirs but none match, the registered cwd is not where this agent runs.`
34846
+ );
34847
+ } catch (err) {
34848
+ logger.warn(
34849
+ `Register: NO local session found for cwd=${cwd} (auto-wake WILL be refused); could not describe the transcript base: ${err.message}`
34850
+ );
34851
+ }
34852
+ }
34683
34853
  autoRelay.setLocalPeer(peerId, localSessionId, cwd, mode, label, localSessionId);
34684
34854
  const result = {
34685
34855
  success: true,
@@ -34688,7 +34858,12 @@ function registerRegisterPeerTool(server) {
34688
34858
  sessionResolution: {
34689
34859
  decision: resolution.decision,
34690
34860
  confidence: resolution.confidence,
34691
- candidateCount: resolution.candidateCount
34861
+ candidateCount: resolution.candidateCount,
34862
+ // Only on the broken path — keeps the happy-path result terse.
34863
+ ...noLocalSession ? {
34864
+ warning: "No local session transcript found for this cwd \u2014 auto-wake will be REFUSED. Verify the cwd is where this agent actually runs and that CLAUDE_CONFIG_DIR / CODEX_HOME are visible to the bridge process.",
34865
+ scannedPaths: resolution.probedPaths ?? []
34866
+ } : {}
34692
34867
  }
34693
34868
  };
34694
34869
  const relayAdvisory = peer?.advisory;
@@ -34758,6 +34933,7 @@ var init_register_peer = __esm({
34758
34933
  init_heartbeat();
34759
34934
  init_auto_relay();
34760
34935
  init_session_resolver();
34936
+ init_cc_cli();
34761
34937
  init_durable_identity();
34762
34938
  init_constants();
34763
34939
  init_npm_update_check();
@@ -35832,7 +36008,7 @@ var init_health_check2 = __esm({
35832
36008
  });
35833
36009
 
35834
36010
  // src/tools/create-session.ts
35835
- import crypto6 from "node:crypto";
36011
+ import crypto7 from "node:crypto";
35836
36012
  function registerCreateSessionTool(server) {
35837
36013
  server.registerTool(
35838
36014
  "cogent_create_session",
@@ -35863,7 +36039,7 @@ function registerCreateSessionTool(server) {
35863
36039
  )
35864
36040
  );
35865
36041
  }
35866
- const sessionSecret = secret ?? crypto6.randomBytes(16).toString("hex");
36042
+ const sessionSecret = secret ?? crypto7.randomBytes(16).toString("hex");
35867
36043
  const resp = await fetch(
35868
36044
  `${config2.COGENT_ENDPOINT}/api/sessions`,
35869
36045
  {
@@ -36187,13 +36363,13 @@ var init_setup_mail = __esm({
36187
36363
  });
36188
36364
 
36189
36365
  // src/mail/mail-sender.ts
36190
- import fs15 from "node:fs/promises";
36191
- import path16 from "node:path";
36366
+ import fs16 from "node:fs/promises";
36367
+ import path17 from "node:path";
36192
36368
  async function buildAndSendMail(sender, creds, params) {
36193
36369
  const attachments = [];
36194
36370
  for (const p of params.attachmentPaths ?? []) {
36195
- const content = await fs15.readFile(p);
36196
- attachments.push({ filename: path16.basename(p), content });
36371
+ const content = await fs16.readFile(p);
36372
+ attachments.push({ filename: path17.basename(p), content });
36197
36373
  }
36198
36374
  const { messageId } = await sender.send({
36199
36375
  from: creds.address,
@@ -36321,16 +36497,16 @@ var init_send_mail = __esm({
36321
36497
  });
36322
36498
 
36323
36499
  // src/mail/mail-fetcher.ts
36324
- import fs16 from "node:fs/promises";
36325
- import path17 from "node:path";
36500
+ import fs17 from "node:fs/promises";
36501
+ import path18 from "node:path";
36326
36502
  async function saveAttachments(attachments, downloadDir) {
36327
36503
  if (attachments.length === 0) return [];
36328
- await fs16.mkdir(downloadDir, { recursive: true });
36504
+ await fs17.mkdir(downloadDir, { recursive: true });
36329
36505
  const saved = [];
36330
36506
  for (const a of attachments) {
36331
- const name = path17.basename(a.filename) || "attachment";
36332
- const savedPath = path17.join(downloadDir, name);
36333
- await fs16.writeFile(savedPath, a.content);
36507
+ const name = path18.basename(a.filename) || "attachment";
36508
+ const savedPath = path18.join(downloadDir, name);
36509
+ await fs17.writeFile(savedPath, a.content);
36334
36510
  saved.push({ filename: name, savedPath, size: a.content.length });
36335
36511
  }
36336
36512
  return saved;
@@ -36461,8 +36637,8 @@ var init_mail_fetcher = __esm({
36461
36637
  });
36462
36638
 
36463
36639
  // src/tools/fetch-mail.ts
36464
- import os10 from "node:os";
36465
- import path18 from "node:path";
36640
+ import os12 from "node:os";
36641
+ import path19 from "node:path";
36466
36642
  function registerFetchMailTool(server, deps = {}) {
36467
36643
  const makeFetcher = deps.fetcherFactory ?? ((creds) => new ImapflowMailFetcher(creds));
36468
36644
  server.registerTool(
@@ -36524,7 +36700,7 @@ var init_fetch_mail = __esm({
36524
36700
  init_mail_fetcher();
36525
36701
  init_auth_error();
36526
36702
  init_validate();
36527
- DEFAULT_DOWNLOAD_DIR = path18.join(os10.homedir(), ".cogent", "mail-downloads");
36703
+ DEFAULT_DOWNLOAD_DIR = path19.join(os12.homedir(), ".cogent", "mail-downloads");
36528
36704
  }
36529
36705
  });
36530
36706
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@essentialai/cogent-bridge-bundled",
3
- "version": "3.20.6",
3
+ "version": "3.21.0",
4
4
  "description": "Zero-dependency, pre-bundled Cogent MCP bridge — a single self-contained file for fast cold `npx` startup (used by the Codex plugin, whose MCP startup window is short). Functionally identical to @essentialai/cogent-bridge; carries no npm dependencies so `npx` skips dependency install.",
5
5
  "type": "module",
6
6
  "bin": {