@essentialai/cogent-bridge-bundled 3.22.0 → 3.23.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 (2) hide show
  1. package/cogent-bridge.mjs +368 -133
  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: path20, errorMaps, issueData } = params;
1263
- const fullPath = [...path20, ...issueData.path || []];
1262
+ const { data, path: path21, errorMaps, issueData } = params;
1263
+ const fullPath = [...path21, ...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, path20, key) {
1543
+ constructor(parent, value, path21, key) {
1544
1544
  this._cachedPath = [];
1545
1545
  this.parent = parent;
1546
1546
  this.data = value;
1547
- this._path = path20;
1547
+ this._path = path21;
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, path20) {
5000
- if (!path20)
4999
+ function getElementAtPath(obj, path21) {
5000
+ if (!path21)
5001
5001
  return obj;
5002
- return path20.reduce((acc, key) => acc?.[key], obj);
5002
+ return path21.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(path20, issues) {
5251
+ function prefixIssues(path21, issues) {
5252
5252
  return issues.map((iss) => {
5253
5253
  var _a;
5254
5254
  (_a = iss).path ?? (_a.path = []);
5255
- iss.path.unshift(path20);
5255
+ iss.path.unshift(path21);
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(path20) {
17062
- let input = path20;
17061
+ function removeDotSegments(path21) {
17062
+ let input = path21;
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 [path20, query] = wsComponent.resourceName.split("?");
17262
- wsComponent.path = path20 && path20 !== "/" ? path20 : void 0;
17261
+ const [path21, query] = wsComponent.resourceName.split("?");
17262
+ wsComponent.path = path21 && path21 !== "/" ? path21 : 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, fs18, exportName) {
20615
+ function addFormats(ajv, list, fs19, 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, fs18[f]);
20620
+ ajv.addFormat(f, fs19[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: path20, errorMaps, issueData } = params;
21733
- const fullPath = [...path20, ...issueData.path || []];
21732
+ const { data, path: path21, errorMaps, issueData } = params;
21733
+ const fullPath = [...path21, ...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, path20, key) {
21887
+ constructor(parent, value, path21, key) {
21888
21888
  this._cachedPath = [];
21889
21889
  this.parent = parent;
21890
21890
  this.data = value;
21891
- this._path = path20;
21891
+ this._path = path21;
21892
21892
  this._key = key;
21893
21893
  }
21894
21894
  get path() {
@@ -25477,10 +25477,10 @@ var require_zod = __commonJS({
25477
25477
  };
25478
25478
  Object.defineProperty(exports, "__esModule", { value: true });
25479
25479
  exports.z = void 0;
25480
- var z18 = __importStar(require_external());
25481
- exports.z = z18;
25480
+ var z19 = __importStar(require_external());
25481
+ exports.z = z19;
25482
25482
  __exportStar(require_external(), exports);
25483
- exports.default = z18;
25483
+ exports.default = z19;
25484
25484
  }
25485
25485
  });
25486
25486
 
@@ -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.22.0") {
26393
- return "3.22.0";
26392
+ if ("3.23.1") {
26393
+ return "3.23.1";
26394
26394
  }
26395
26395
  try {
26396
26396
  const require2 = createRequire(import.meta.url);
@@ -27826,7 +27826,7 @@ var init_http_backend = __esm({
27826
27826
  * in cloud mode we ignore it and use this.sessionId (the cloud session).
27827
27827
  */
27828
27828
  async registerPeer(peerId, _sessionId, cwd, label, clientVersion, mode, _channelSessionId, capabilities, workspaceId, threadId, peerSecret) {
27829
- const path20 = PATHS.peers.replace(":sessionId", this.sessionId);
27829
+ const path21 = PATHS.peers.replace(":sessionId", this.sessionId);
27830
27830
  const body = {
27831
27831
  peerId,
27832
27832
  cwd,
@@ -27857,7 +27857,7 @@ var init_http_backend = __esm({
27857
27857
  if (peerSecret !== void 0 && await relaySupports(this.http, "peer-ownership")) {
27858
27858
  body.peerSecret = peerSecret;
27859
27859
  }
27860
- return this.http.post(path20, body);
27860
+ return this.http.post(path21, body);
27861
27861
  }
27862
27862
  /**
27863
27863
  * Deregister a peer from the cloud session.
@@ -27869,9 +27869,9 @@ var init_http_backend = __esm({
27869
27869
  * local mail creds. A 404 (peer not found) resolves to `{ removed: false, ... }`, not a throw.
27870
27870
  */
27871
27871
  async deregisterPeer(peerId) {
27872
- const path20 = PATHS.peer.replace(":sessionId", this.sessionId).replace(":peerId", peerId);
27872
+ const path21 = PATHS.peer.replace(":sessionId", this.sessionId).replace(":peerId", peerId);
27873
27873
  try {
27874
- const headers = await this.http.delete(path20, {});
27874
+ const headers = await this.http.delete(path21, {});
27875
27875
  const mailboxDeprovisioned = headers.get(MAILBOX_DEPROVISIONED_HEADER) === "true";
27876
27876
  return { removed: true, mailboxDeprovisioned };
27877
27877
  } catch (err) {
@@ -27895,8 +27895,8 @@ var init_http_backend = __esm({
27895
27895
  * GET /api/sessions/:sessionId/peers
27896
27896
  */
27897
27897
  async listPeers() {
27898
- const path20 = PATHS.peers.replace(":sessionId", this.sessionId);
27899
- const result = await this.http.get(path20);
27898
+ const path21 = PATHS.peers.replace(":sessionId", this.sessionId);
27899
+ const result = await this.http.get(path21);
27900
27900
  return result.peers;
27901
27901
  }
27902
27902
  /**
@@ -27904,8 +27904,8 @@ var init_http_backend = __esm({
27904
27904
  * Calls the lightweight heartbeat endpoint on the cloud relay server.
27905
27905
  */
27906
27906
  async updateLastSeen(peerId) {
27907
- const path20 = PATHS.heartbeat.replace(":sessionId", this.sessionId);
27908
- await this.http.post(path20, { peerId });
27907
+ const path21 = PATHS.heartbeat.replace(":sessionId", this.sessionId);
27908
+ await this.http.post(path21, { peerId });
27909
27909
  }
27910
27910
  /**
27911
27911
  * Record a message in the cloud session.
@@ -27916,7 +27916,7 @@ var init_http_backend = __esm({
27916
27916
  * the input record to construct a full MessageRecord.
27917
27917
  */
27918
27918
  async recordMessage(record2) {
27919
- const path20 = PATHS.messages.replace(":sessionId", this.sessionId);
27919
+ const path21 = PATHS.messages.replace(":sessionId", this.sessionId);
27920
27920
  const body = {
27921
27921
  fromPeerId: record2.fromPeerId,
27922
27922
  toPeerId: record2.toPeerId,
@@ -27939,7 +27939,7 @@ var init_http_backend = __esm({
27939
27939
  if (record2.attachments && record2.attachments.length > 0) {
27940
27940
  body.attachments = record2.attachments;
27941
27941
  }
27942
- const resp = await this.http.post(path20, body);
27942
+ const resp = await this.http.post(path21, body);
27943
27943
  return {
27944
27944
  ...record2,
27945
27945
  id: resp.id,
@@ -27953,7 +27953,7 @@ var init_http_backend = __esm({
27953
27953
  * Supports optional peerId filter and limit (default 300).
27954
27954
  */
27955
27955
  async getHistory(peerId, limit, includeRelayEchoes, metadataOnly, dedupInferredEchoes) {
27956
- const path20 = PATHS.messages.replace(":sessionId", this.sessionId);
27956
+ const path21 = PATHS.messages.replace(":sessionId", this.sessionId);
27957
27957
  const query = {};
27958
27958
  if (peerId) {
27959
27959
  query.peerId = peerId;
@@ -27968,7 +27968,7 @@ var init_http_backend = __esm({
27968
27968
  if (dedupInferredEchoes) {
27969
27969
  query.dedupInferredEchoes = "true";
27970
27970
  }
27971
- const result = await this.http.get(path20, query);
27971
+ const result = await this.http.get(path21, query);
27972
27972
  return result.messages;
27973
27973
  }
27974
27974
  /**
@@ -27979,12 +27979,12 @@ var init_http_backend = __esm({
27979
27979
  * so that get-history shows the actual response (not null).
27980
27980
  */
27981
27981
  async updateMessageResponse(messageId, response, durationMs, pending) {
27982
- const path20 = PATHS.message.replace(":sessionId", this.sessionId).replace(":messageId", messageId);
27982
+ const path21 = PATHS.message.replace(":sessionId", this.sessionId).replace(":messageId", messageId);
27983
27983
  const body = { response, durationMs };
27984
27984
  if (pending === true) {
27985
27985
  body.pending = true;
27986
27986
  }
27987
- await this.http.patch(path20, body);
27987
+ await this.http.patch(path21, body);
27988
27988
  }
27989
27989
  /**
27990
27990
  * Validate a session.
@@ -28126,8 +28126,8 @@ var init_http_client = __esm({
28126
28126
  * Perform an authenticated GET request.
28127
28127
  * Appends query parameters to the URL if provided.
28128
28128
  */
28129
- async get(path20, query) {
28130
- const url = new URL(path20, this.baseUrl);
28129
+ async get(path21, query) {
28130
+ const url = new URL(path21, this.baseUrl);
28131
28131
  if (query) {
28132
28132
  for (const [k, v] of Object.entries(query)) {
28133
28133
  url.searchParams.set(k, v);
@@ -28142,8 +28142,8 @@ var init_http_client = __esm({
28142
28142
  /**
28143
28143
  * Perform an authenticated POST request with a JSON body.
28144
28144
  */
28145
- async post(path20, body) {
28146
- const url = new URL(path20, this.baseUrl);
28145
+ async post(path21, body) {
28146
+ const url = new URL(path21, this.baseUrl);
28147
28147
  const resp = await this.fetchWithTimeout(url, {
28148
28148
  method: "POST",
28149
28149
  headers: this.headers(),
@@ -28161,8 +28161,8 @@ var init_http_client = __esm({
28161
28161
  * Perform an authenticated PATCH request with a JSON body.
28162
28162
  * Used to update existing resources (e.g., message response fields).
28163
28163
  */
28164
- async patch(path20, body) {
28165
- const url = new URL(path20, this.baseUrl);
28164
+ async patch(path21, body) {
28165
+ const url = new URL(path21, this.baseUrl);
28166
28166
  const resp = await this.fetchWithTimeout(url, {
28167
28167
  method: "PATCH",
28168
28168
  headers: this.headers(),
@@ -28187,8 +28187,8 @@ var init_http_client = __esm({
28187
28187
  * "Malformed JSON in request body" 400 from cogent-server <=3.1.2 when
28188
28188
  * any client (including third-party tools) DELETEd a peer without a body.
28189
28189
  */
28190
- async delete(path20, body) {
28191
- const url = new URL(path20, this.baseUrl);
28190
+ async delete(path21, body) {
28191
+ const url = new URL(path21, this.baseUrl);
28192
28192
  const headers = {
28193
28193
  "Authorization": `Bearer ${this.token}`
28194
28194
  };
@@ -32371,14 +32371,14 @@ var init_ws_client = __esm({
32371
32371
  if (this.pollTimer) return;
32372
32372
  const poll = async () => {
32373
32373
  try {
32374
- const path20 = `/api/sessions/${this.opts.sessionId}/poll`;
32374
+ const path21 = `/api/sessions/${this.opts.sessionId}/poll`;
32375
32375
  const query = {
32376
32376
  peerId: this.opts.peerId
32377
32377
  };
32378
32378
  if (this.lastMessageId) {
32379
32379
  query.lastMessageId = this.lastMessageId;
32380
32380
  }
32381
- const result = await this.opts.http.get(path20, query);
32381
+ const result = await this.opts.http.get(path21, query);
32382
32382
  if (result.messages && result.messages.length > 0) {
32383
32383
  this.opts.onMessages(result.messages);
32384
32384
  this.lastMessageId = result.messages[result.messages.length - 1].id;
@@ -33097,6 +33097,112 @@ var init_exec_remote = __esm({
33097
33097
  }
33098
33098
  });
33099
33099
 
33100
+ // src/services/wake-log.ts
33101
+ import { execFileSync } from "node:child_process";
33102
+ import crypto4 from "node:crypto";
33103
+ import fs13 from "node:fs";
33104
+ import os9 from "node:os";
33105
+ import path14 from "node:path";
33106
+ function hashCwd2(cwd) {
33107
+ return crypto4.createHash("sha256").update(path14.resolve(cwd)).digest("hex").slice(0, 16);
33108
+ }
33109
+ function wakeLogPath(cwd) {
33110
+ return path14.join(os9.homedir(), ".cogent", "wake-log", `${hashCwd2(cwd)}.jsonl`);
33111
+ }
33112
+ function git(cwd, args) {
33113
+ return execFileSync("git", ["-C", cwd, ...args], {
33114
+ encoding: "utf-8",
33115
+ timeout: 15e3,
33116
+ stdio: ["ignore", "pipe", "ignore"]
33117
+ });
33118
+ }
33119
+ function captureTreeState(cwd) {
33120
+ try {
33121
+ const head = git(cwd, ["rev-parse", "HEAD"]).trim();
33122
+ const entries = {};
33123
+ const raw = git(cwd, ["status", "--porcelain=v1", "-z", "--untracked-files=all"]);
33124
+ const fields = raw.split("\0").filter((f) => f.length > 0);
33125
+ for (let i = 0; i < fields.length; i++) {
33126
+ const field = fields[i];
33127
+ const status = field.slice(0, 2);
33128
+ entries[field.slice(3)] = status;
33129
+ if (status[0] === "R" || status[0] === "C") i++;
33130
+ }
33131
+ return { head, entries };
33132
+ } catch {
33133
+ return null;
33134
+ }
33135
+ }
33136
+ function diffTreeState(before, after) {
33137
+ if (!before || !after) return null;
33138
+ const changed = /* @__PURE__ */ new Set();
33139
+ if (before.head !== after.head) changed.add("HEAD");
33140
+ for (const [file, status] of Object.entries(after.entries)) {
33141
+ if (before.entries[file] !== status) changed.add(file);
33142
+ }
33143
+ for (const file of Object.keys(before.entries)) {
33144
+ if (!(file in after.entries)) changed.add(file);
33145
+ }
33146
+ return [...changed].sort();
33147
+ }
33148
+ function preview(message) {
33149
+ return message.length > PREVIEW_LIMIT ? `${message.slice(0, PREVIEW_LIMIT)}\u2026` : message;
33150
+ }
33151
+ function appendWakeRecord(record2, cwd) {
33152
+ const target = wakeLogPath(cwd);
33153
+ try {
33154
+ fs13.mkdirSync(path14.dirname(target), { recursive: true });
33155
+ const row = {
33156
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
33157
+ ...record2,
33158
+ messagePreview: preview(record2.messagePreview ?? "")
33159
+ };
33160
+ fs13.appendFileSync(target, `${JSON.stringify(row)}
33161
+ `);
33162
+ pruneIfNeeded(target);
33163
+ } catch {
33164
+ }
33165
+ }
33166
+ function pruneIfNeeded(target) {
33167
+ try {
33168
+ const lines = fs13.readFileSync(target, "utf-8").split("\n").filter((l) => l.length > 0);
33169
+ if (lines.length <= WAKE_LOG_MAX_RECORDS) return;
33170
+ const kept = lines.slice(lines.length - WAKE_LOG_MAX_RECORDS);
33171
+ const tmp = `${target}.tmp-${process.pid}`;
33172
+ fs13.writeFileSync(tmp, `${kept.join("\n")}
33173
+ `);
33174
+ fs13.renameSync(tmp, target);
33175
+ } catch {
33176
+ }
33177
+ }
33178
+ function readWakeLog(cwd, limit) {
33179
+ let lines;
33180
+ try {
33181
+ lines = fs13.readFileSync(wakeLogPath(cwd), "utf-8").split("\n").filter((l) => l.length > 0);
33182
+ } catch {
33183
+ return [];
33184
+ }
33185
+ const rows = [];
33186
+ for (const line of lines) {
33187
+ try {
33188
+ const parsed = JSON.parse(line);
33189
+ if (parsed && typeof parsed === "object" && typeof parsed.messageId === "string") {
33190
+ rows.push(parsed);
33191
+ }
33192
+ } catch {
33193
+ }
33194
+ }
33195
+ return typeof limit === "number" && limit > 0 ? rows.slice(-limit) : rows;
33196
+ }
33197
+ var WAKE_LOG_MAX_RECORDS, PREVIEW_LIMIT;
33198
+ var init_wake_log = __esm({
33199
+ "src/services/wake-log.ts"() {
33200
+ "use strict";
33201
+ WAKE_LOG_MAX_RECORDS = 500;
33202
+ PREVIEW_LIMIT = 500;
33203
+ }
33204
+ });
33205
+
33100
33206
  // src/services/session-resolver.ts
33101
33207
  function decideResolution(candidates, pinnedSessionId, pinnedExists, marginMs) {
33102
33208
  const sorted = [...candidates].sort((a, b) => b.mtimeMs - a.mtimeMs);
@@ -33184,15 +33290,15 @@ var init_session_resolver = __esm({
33184
33290
  });
33185
33291
 
33186
33292
  // src/services/wake-inflight.ts
33187
- import crypto4 from "node:crypto";
33188
- import fs13 from "node:fs";
33189
- import os9 from "node:os";
33190
- import path14 from "node:path";
33191
- function hashCwd2(cwd) {
33192
- return crypto4.createHash("sha256").update(path14.resolve(cwd)).digest("hex").slice(0, 16);
33293
+ import crypto5 from "node:crypto";
33294
+ import fs14 from "node:fs";
33295
+ import os10 from "node:os";
33296
+ import path15 from "node:path";
33297
+ function hashCwd3(cwd) {
33298
+ return crypto5.createHash("sha256").update(path15.resolve(cwd)).digest("hex").slice(0, 16);
33193
33299
  }
33194
33300
  function wakeInflightPath(peerId, cwd = process.cwd()) {
33195
- return path14.join(os9.homedir(), ".cogent", "wake-inflight", `${hashCwd2(cwd)}.${safe(peerId)}.json`);
33301
+ return path15.join(os10.homedir(), ".cogent", "wake-inflight", `${hashCwd3(cwd)}.${safe(peerId)}.json`);
33196
33302
  }
33197
33303
  function ttlMs() {
33198
33304
  let timeout = 3e5;
@@ -33205,17 +33311,17 @@ function ttlMs() {
33205
33311
  }
33206
33312
  function readFileSafe(p) {
33207
33313
  try {
33208
- const parsed = JSON.parse(fs13.readFileSync(p, "utf-8"));
33314
+ const parsed = JSON.parse(fs14.readFileSync(p, "utf-8"));
33209
33315
  return parsed && typeof parsed === "object" && parsed.messages ? parsed : { messages: {} };
33210
33316
  } catch {
33211
33317
  return { messages: {} };
33212
33318
  }
33213
33319
  }
33214
33320
  function writeAtomic(p, data) {
33215
- fs13.mkdirSync(path14.dirname(p), { recursive: true });
33321
+ fs14.mkdirSync(path15.dirname(p), { recursive: true });
33216
33322
  const tmp = `${p}.${process.pid}.tmp`;
33217
- fs13.writeFileSync(tmp, JSON.stringify(data, null, 2) + "\n", "utf-8");
33218
- fs13.renameSync(tmp, p);
33323
+ fs14.writeFileSync(tmp, JSON.stringify(data, null, 2) + "\n", "utf-8");
33324
+ fs14.renameSync(tmp, p);
33219
33325
  }
33220
33326
  function prune(f, now) {
33221
33327
  for (const [id, rec] of Object.entries(f.messages)) {
@@ -33235,6 +33341,15 @@ function markWakeInFlight(peerId, messageId, traceId, cwd = process.cwd()) {
33235
33341
  logger.debug(`wake-inflight: could not mark ${messageId}: ${err}`);
33236
33342
  }
33237
33343
  }
33344
+ function listWakeInFlight(peerId, cwd = process.cwd()) {
33345
+ try {
33346
+ const cur = readFileSafe(wakeInflightPath(peerId, cwd));
33347
+ const now = Date.now();
33348
+ return Object.entries(cur.messages).filter(([, e]) => e.expiresAt > now).map(([messageId, e]) => ({ messageId, ...e })).sort((a, b) => a.startedAt - b.startedAt);
33349
+ } catch {
33350
+ return [];
33351
+ }
33352
+ }
33238
33353
  function clearWakeInFlight(peerId, messageId, cwd = process.cwd()) {
33239
33354
  try {
33240
33355
  const p = wakeInflightPath(peerId, cwd);
@@ -33391,6 +33506,7 @@ var init_auto_relay = __esm({
33391
33506
  "src/services/auto-relay.ts"() {
33392
33507
  "use strict";
33393
33508
  init_exec_remote();
33509
+ init_wake_log();
33394
33510
  init_session_resolver();
33395
33511
  init_config();
33396
33512
  init_backend();
@@ -33986,6 +34102,10 @@ var init_auto_relay = __esm({
33986
34102
  const traceId = msg.traceId ?? randomUUID2();
33987
34103
  const startMs = Date.now();
33988
34104
  let replied = false;
34105
+ let treeBefore = null;
34106
+ let wakeExitCode = null;
34107
+ let refused = false;
34108
+ let threw = false;
33989
34109
  try {
33990
34110
  const res = await this.refreshSessionId();
33991
34111
  this._trace(traceId, "resolved", {
@@ -33995,6 +34115,7 @@ var init_auto_relay = __esm({
33995
34115
  mtimeGapMs: res.mtimeGapMs
33996
34116
  });
33997
34117
  if (!res.sessionId) {
34118
+ refused = true;
33998
34119
  this._trace(traceId, "refused", {
33999
34120
  decision: res.decision,
34000
34121
  candidateCount: res.candidateCount
@@ -34023,6 +34144,7 @@ var init_auto_relay = __esm({
34023
34144
  decision: res.decision,
34024
34145
  confidence: res.confidence
34025
34146
  });
34147
+ treeBefore = captureTreeState(this.localCwd);
34026
34148
  const result = await execRemote(
34027
34149
  getConfig().COGENT_PLATFORM,
34028
34150
  this.localSessionId,
@@ -34035,6 +34157,7 @@ var init_auto_relay = __esm({
34035
34157
  { idempotencyKey: msg.id }
34036
34158
  );
34037
34159
  const durationMs = Date.now() - startMs;
34160
+ wakeExitCode = result.exitCode;
34038
34161
  if (result.exitCode === 0 && result.stdout) {
34039
34162
  await this._relayCapturedReply(msg, result, traceId, durationMs, false);
34040
34163
  replied = true;
@@ -34100,6 +34223,7 @@ var init_auto_relay = __esm({
34100
34223
  }
34101
34224
  } catch (err) {
34102
34225
  const durationMs = Date.now() - startMs;
34226
+ threw = true;
34103
34227
  this._trace(traceId, "failed", { threw: true, durationMs });
34104
34228
  logger.error(`Auto-relay: execRemote threw after ${durationMs}ms: ${err}`);
34105
34229
  if (!replied) {
@@ -34107,6 +34231,48 @@ var init_auto_relay = __esm({
34107
34231
  stderr: `EXEC_THREW: ${err}`
34108
34232
  });
34109
34233
  }
34234
+ } finally {
34235
+ this._recordWake(msg, traceId, {
34236
+ outcome: threw ? "threw" : refused ? "refused" : replied ? "replied" : "failed",
34237
+ exitCode: wakeExitCode,
34238
+ durationMs: Date.now() - startMs,
34239
+ treeBefore
34240
+ });
34241
+ }
34242
+ }
34243
+ /**
34244
+ * Write the durable wake record. Wrapped whole: visibility must never be able to fail a
34245
+ * wake that would otherwise have succeeded, so every error here is swallowed and logged.
34246
+ */
34247
+ _recordWake(msg, traceId, outcome) {
34248
+ try {
34249
+ const cwd = this.localCwd;
34250
+ if (!cwd) return;
34251
+ const filesChanged = outcome.treeBefore ? diffTreeState(outcome.treeBefore, captureTreeState(cwd)) : null;
34252
+ appendWakeRecord(
34253
+ {
34254
+ traceId,
34255
+ messageId: msg.id,
34256
+ fromPeerId: msg.fromPeerId,
34257
+ toPeerId: this.localPeerId ?? "",
34258
+ cwd,
34259
+ sessionId: this.localSessionId ?? "",
34260
+ platform: getConfig().COGENT_PLATFORM,
34261
+ outcome: outcome.outcome,
34262
+ exitCode: outcome.exitCode,
34263
+ durationMs: outcome.durationMs,
34264
+ filesChanged,
34265
+ messagePreview: msg.message ?? ""
34266
+ },
34267
+ cwd
34268
+ );
34269
+ if (filesChanged && filesChanged.length > 0) {
34270
+ logger.info(
34271
+ `Auto-relay: wake for message ${msg.id} from ${msg.fromPeerId} changed ${filesChanged.length} path(s): ${filesChanged.slice(0, 10).join(", ")}`
34272
+ );
34273
+ }
34274
+ } catch (err) {
34275
+ logger.warn(`Auto-relay: wake-log record failed (wake itself unaffected): ${err}`);
34110
34276
  }
34111
34277
  }
34112
34278
  /**
@@ -34499,9 +34665,9 @@ __export(startup_exports, {
34499
34665
  setInboxNotifier: () => setInboxNotifier,
34500
34666
  triggerReRegistration: () => triggerReRegistration
34501
34667
  });
34502
- import os10 from "node:os";
34503
- import path15 from "node:path";
34504
- import fs14 from "node:fs/promises";
34668
+ import os11 from "node:os";
34669
+ import path16 from "node:path";
34670
+ import fs15 from "node:fs/promises";
34505
34671
  import readline2 from "node:readline";
34506
34672
  import { execFile as execFile5 } from "node:child_process";
34507
34673
  import { promisify as promisify4 } from "node:util";
@@ -34519,7 +34685,7 @@ function bindInboxNotifier() {
34519
34685
  }
34520
34686
  async function loadPersistedConfig() {
34521
34687
  try {
34522
- const raw = await fs14.readFile(PERSIST_PATH, "utf-8");
34688
+ const raw = await fs15.readFile(PERSIST_PATH, "utf-8");
34523
34689
  return JSON.parse(raw);
34524
34690
  } catch {
34525
34691
  return {};
@@ -34527,7 +34693,7 @@ async function loadPersistedConfig() {
34527
34693
  }
34528
34694
  async function savePersistedConfig(config2) {
34529
34695
  try {
34530
- await fs14.writeFile(PERSIST_PATH, JSON.stringify(config2, null, 2) + "\n", "utf-8");
34696
+ await fs15.writeFile(PERSIST_PATH, JSON.stringify(config2, null, 2) + "\n", "utf-8");
34531
34697
  } catch (err) {
34532
34698
  const msg = err instanceof Error ? err.message : String(err);
34533
34699
  logger.warn(`Could not save config to ${PERSIST_PATH}: ${msg}`);
@@ -34562,11 +34728,11 @@ First run detected. Where should cogent-bridge store its data?
34562
34728
  });
34563
34729
  }
34564
34730
  async function validateStateDir(statePath) {
34565
- await fs14.mkdir(statePath, { recursive: true });
34566
- const testFile = path15.join(statePath, ".write-test");
34731
+ await fs15.mkdir(statePath, { recursive: true });
34732
+ const testFile = path16.join(statePath, ".write-test");
34567
34733
  try {
34568
- await fs14.writeFile(testFile, "test", "utf-8");
34569
- await fs14.unlink(testFile);
34734
+ await fs15.writeFile(testFile, "test", "utf-8");
34735
+ await fs15.unlink(testFile);
34570
34736
  } catch {
34571
34737
  throw new BridgeError(
34572
34738
  "STARTUP_FAILED" /* STARTUP_FAILED */,
@@ -34753,10 +34919,10 @@ async function runStartup() {
34753
34919
  if (envStatePath) {
34754
34920
  statePath = envStatePath;
34755
34921
  } else {
34756
- const defaultPath = path15.join(os10.homedir(), ".cogent");
34922
+ const defaultPath = path16.join(os11.homedir(), ".cogent");
34757
34923
  statePath = await firstRunPrompt(defaultPath);
34758
34924
  }
34759
- if (!envStatePath && statePath !== path15.join(os10.homedir(), ".cogent")) {
34925
+ if (!envStatePath && statePath !== path16.join(os11.homedir(), ".cogent")) {
34760
34926
  process.env.COGENT_STATE_PATH = statePath;
34761
34927
  } else if (!envStatePath) {
34762
34928
  process.env.COGENT_STATE_PATH = statePath;
@@ -34820,7 +34986,7 @@ async function runStartup() {
34820
34986
  }
34821
34987
  initLogger(
34822
34988
  config2.COGENT_LOG_LEVEL,
34823
- path15.join(config2.COGENT_STATE_PATH, "logs")
34989
+ path16.join(config2.COGENT_STATE_PATH, "logs")
34824
34990
  );
34825
34991
  if (isCloud && effectiveSessionId && effectiveToken) {
34826
34992
  cloudInbox = new MessageInbox();
@@ -34882,7 +35048,7 @@ var init_startup = __esm({
34882
35048
  init_auto_relay();
34883
35049
  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;
34884
35050
  execFileAsync3 = promisify4(execFile5);
34885
- PERSIST_PATH = path15.join(os10.homedir(), ".cogent-config.json");
35051
+ PERSIST_PATH = path16.join(os11.homedir(), ".cogent-config.json");
34886
35052
  legacyWarnEmitted = false;
34887
35053
  cloudWsClient = null;
34888
35054
  cloudInbox = null;
@@ -34896,13 +35062,13 @@ var init_startup = __esm({
34896
35062
  });
34897
35063
 
34898
35064
  // src/cloud/mail-credential-store.ts
34899
- import crypto5 from "node:crypto";
34900
- import fs15 from "node:fs/promises";
34901
- import path16 from "node:path";
34902
- import os11 from "node:os";
35065
+ import crypto6 from "node:crypto";
35066
+ import fs16 from "node:fs/promises";
35067
+ import path17 from "node:path";
35068
+ import os12 from "node:os";
34903
35069
  function defaultMailCredentialPath(cwd = process.cwd()) {
34904
- const hash = crypto5.createHash("sha256").update(path16.resolve(cwd)).digest("hex").slice(0, 16);
34905
- return path16.join(os11.homedir(), ".cogent", "mail-credentials", `${hash}.json`);
35070
+ const hash = crypto6.createHash("sha256").update(path17.resolve(cwd)).digest("hex").slice(0, 16);
35071
+ return path17.join(os12.homedir(), ".cogent", "mail-credentials", `${hash}.json`);
34906
35072
  }
34907
35073
  function resolveMailCredentialPath(credentialPath) {
34908
35074
  if (credentialPath) return credentialPath;
@@ -34913,16 +35079,16 @@ function resolveMailCredentialPath(credentialPath) {
34913
35079
  async function loadMailCredentials(credentialPath) {
34914
35080
  const filePath = resolveMailCredentialPath(credentialPath);
34915
35081
  try {
34916
- return JSON.parse(await fs15.readFile(filePath, "utf-8"));
35082
+ return JSON.parse(await fs16.readFile(filePath, "utf-8"));
34917
35083
  } catch {
34918
35084
  return null;
34919
35085
  }
34920
35086
  }
34921
35087
  async function saveMailCredentials(creds, credentialPath) {
34922
35088
  const filePath = resolveMailCredentialPath(credentialPath);
34923
- await fs15.mkdir(path16.dirname(filePath), { recursive: true, mode: 448 });
34924
- await fs15.writeFile(filePath, JSON.stringify(creds, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
34925
- await fs15.chmod(filePath, 384);
35089
+ await fs16.mkdir(path17.dirname(filePath), { recursive: true, mode: 448 });
35090
+ await fs16.writeFile(filePath, JSON.stringify(creds, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
35091
+ await fs16.chmod(filePath, 384);
34926
35092
  }
34927
35093
  async function persistProvisionedMailbox(mailbox, credentialPath) {
34928
35094
  if (!mailbox?.address || !mailbox.password) return false;
@@ -34943,21 +35109,22 @@ async function persistProvisionedMailbox(mailbox, credentialPath) {
34943
35109
  async function clearMailCredentials(credentialPath) {
34944
35110
  const filePath = resolveMailCredentialPath(credentialPath);
34945
35111
  try {
34946
- await fs15.unlink(filePath);
35112
+ await fs16.unlink(filePath);
34947
35113
  } catch (err) {
34948
35114
  if (err.code !== "ENOENT") throw err;
34949
35115
  }
34950
35116
  }
34951
- var MAIL_DEFAULT_HOST;
35117
+ var MAIL_NOT_CONFIGURED_HINT, MAIL_DEFAULT_HOST;
34952
35118
  var init_mail_credential_store = __esm({
34953
35119
  "src/cloud/mail-credential-store.ts"() {
34954
35120
  "use strict";
35121
+ MAIL_NOT_CONFIGURED_HINT = "Cogent Mail requires a Team channel, where each agent's mailbox is provisioned AUTOMATICALLY when it registers \u2014 there is nothing to set up by hand and no password for anyone to hand over. If this IS a Team channel, restart the agent so it re-registers and retries provisioning (the relay logs the reason if it fails). Free channels do not have mailboxes. cogent_setup_mail remains available for a self-hosted or manually provisioned mailbox.";
34955
35122
  MAIL_DEFAULT_HOST = "mail.cogent.tools";
34956
35123
  }
34957
35124
  });
34958
35125
 
34959
35126
  // src/tools/register-peer.ts
34960
- import crypto6 from "node:crypto";
35127
+ import crypto7 from "node:crypto";
34961
35128
  function unresolvedSessionReason(r) {
34962
35129
  if (r.sessionId) return null;
34963
35130
  return r.candidateCount === 0 ? "no-candidates" : "ambiguous";
@@ -35023,7 +35190,7 @@ function registerRegisterPeerTool(server) {
35023
35190
  }
35024
35191
  }
35025
35192
  if (!cloudSessionId) {
35026
- autoSecret = crypto6.randomBytes(16).toString("hex");
35193
+ autoSecret = crypto7.randomBytes(16).toString("hex");
35027
35194
  const resp = await fetch(
35028
35195
  `${endpoint}/api/sessions`,
35029
35196
  {
@@ -35122,6 +35289,11 @@ function registerRegisterPeerTool(server) {
35122
35289
  );
35123
35290
  }
35124
35291
  }
35292
+ if (peer?.mailboxError) {
35293
+ logger.warn(
35294
+ `Cogent Mail: mailbox provisioning FAILED (${peer.mailboxError.code}) \u2014 ${peer.mailboxError.message}`
35295
+ );
35296
+ }
35125
35297
  try {
35126
35298
  if (await persistProvisionedMailbox(peer?.mailbox)) {
35127
35299
  logger.info(`Cogent Mail: saved auto-provisioned mailbox ${peer.mailbox?.address}`);
@@ -36338,8 +36510,69 @@ var init_health_check2 = __esm({
36338
36510
  }
36339
36511
  });
36340
36512
 
36513
+ // src/tools/wake-log.ts
36514
+ function registerWakeLogTool(server) {
36515
+ server.registerTool(
36516
+ "cogent_wake_log",
36517
+ {
36518
+ title: "Wake Log",
36519
+ description: "Show the auto-resume (wake) sessions Cogent has run in this working directory: which peer's message triggered each one, when, how long it took, the outcome, and WHICH FILES IT CHANGED. Use this when files changed with no corresponding edit in your session, when you need to establish who authored a change before committing it, or to check whether a wake is running now.",
36520
+ inputSchema: {
36521
+ limit: import_zod14.z.number().int().positive().optional().describe("Return only the most recent N wakes (default: all retained)."),
36522
+ peerId: import_zod14.z.string().optional().describe(
36523
+ "Your local peer id. Required to list wakes running RIGHT NOW \u2014 in-flight markers are keyed per peer, and two peers can share one directory."
36524
+ ),
36525
+ cwd: import_zod14.z.string().optional().describe("Directory to inspect (default: this bridge's working directory).")
36526
+ },
36527
+ annotations: {
36528
+ readOnlyHint: true,
36529
+ destructiveHint: false,
36530
+ idempotentHint: true,
36531
+ openWorldHint: false
36532
+ }
36533
+ },
36534
+ async ({ limit, peerId, cwd }) => {
36535
+ try {
36536
+ const target = cwd ?? process.cwd();
36537
+ const wakes = readWakeLog(target, limit);
36538
+ const mutatingWakeCount = wakes.filter(
36539
+ (w) => Array.isArray(w.filesChanged) && w.filesChanged.length > 0
36540
+ ).length;
36541
+ const active = peerId ? listWakeInFlight(peerId, target) : [];
36542
+ return successResult({
36543
+ cwd: target,
36544
+ count: wakes.length,
36545
+ mutatingWakeCount,
36546
+ wakes,
36547
+ active,
36548
+ ...peerId ? {} : { activeHint: "Pass peerId to see wakes running right now (markers are per-peer)." },
36549
+ note: "filesChanged is a git snapshot diff across each wake's window. If you were editing the same tree at the same time, your edits appear here too \u2014 it is what changed while the wake ran, not proof of authorship. null means the directory is not a git worktree."
36550
+ });
36551
+ } catch (err) {
36552
+ return errorResult(
36553
+ new BridgeError(
36554
+ "STATE_CORRUPT" /* STATE_CORRUPT */,
36555
+ `Could not read the wake log: ${err instanceof Error ? err.message : String(err)}`,
36556
+ "The log lives at ~/.cogent/wake-log/<sha256(cwd)[..16]>.jsonl \u2014 check it is readable."
36557
+ )
36558
+ );
36559
+ }
36560
+ }
36561
+ );
36562
+ }
36563
+ var import_zod14;
36564
+ var init_wake_log2 = __esm({
36565
+ "src/tools/wake-log.ts"() {
36566
+ "use strict";
36567
+ import_zod14 = __toESM(require_zod(), 1);
36568
+ init_errors4();
36569
+ init_wake_log();
36570
+ init_wake_inflight();
36571
+ }
36572
+ });
36573
+
36341
36574
  // src/tools/create-session.ts
36342
- import crypto7 from "node:crypto";
36575
+ import crypto8 from "node:crypto";
36343
36576
  function registerCreateSessionTool(server) {
36344
36577
  server.registerTool(
36345
36578
  "cogent_create_session",
@@ -36347,8 +36580,8 @@ function registerCreateSessionTool(server) {
36347
36580
  title: "Create Cloud Session",
36348
36581
  description: "Create a new cloud bridge session on the relay server. Returns session ID and secret for other peers to join. Only available when COGENT_ENDPOINT is configured.",
36349
36582
  inputSchema: {
36350
- label: import_zod14.z.string().optional().describe("Human-readable label for the session"),
36351
- secret: import_zod14.z.string().min(8).optional().describe(
36583
+ label: import_zod15.z.string().optional().describe("Human-readable label for the session"),
36584
+ secret: import_zod15.z.string().min(8).optional().describe(
36352
36585
  "Shared secret for session authentication (min 8 chars). Auto-generated if omitted."
36353
36586
  )
36354
36587
  },
@@ -36370,7 +36603,7 @@ function registerCreateSessionTool(server) {
36370
36603
  )
36371
36604
  );
36372
36605
  }
36373
- const sessionSecret = secret ?? crypto7.randomBytes(16).toString("hex");
36606
+ const sessionSecret = secret ?? crypto8.randomBytes(16).toString("hex");
36374
36607
  const resp = await fetch(
36375
36608
  `${config2.COGENT_ENDPOINT}/api/sessions`,
36376
36609
  {
@@ -36441,11 +36674,11 @@ COGENT_PLATFORM=${config2.COGENT_PLATFORM}`,
36441
36674
  }
36442
36675
  );
36443
36676
  }
36444
- var import_zod14;
36677
+ var import_zod15;
36445
36678
  var init_create_session = __esm({
36446
36679
  "src/tools/create-session.ts"() {
36447
36680
  "use strict";
36448
- import_zod14 = __toESM(require_zod(), 1);
36681
+ import_zod15 = __toESM(require_zod(), 1);
36449
36682
  init_config();
36450
36683
  init_errors4();
36451
36684
  init_credential_store();
@@ -36461,11 +36694,11 @@ function registerJoinSessionTool(server) {
36461
36694
  title: "Join Cloud Channel",
36462
36695
  description: 'Join an existing cloud bridge channel by its channel name (e.g. "mt-space") and shared secret. The channel name is the human-readable label provided by the user, NOT a UUID. Do NOT pass a Claude Code session ID here \u2014 use the channel/space name the user gave you.',
36463
36696
  inputSchema: {
36464
- channel: import_zod15.z.string().describe(
36697
+ channel: import_zod16.z.string().describe(
36465
36698
  'The channel name to join (e.g. "mt-space"). This is the human-readable name the user provided, NOT a UUID. Do NOT use a Claude Code session ID here.'
36466
36699
  ),
36467
- secret: import_zod15.z.string().min(1).describe("The shared secret / password for the channel"),
36468
- orgId: import_zod15.z.string().min(1).optional().describe(
36700
+ secret: import_zod16.z.string().min(1).describe("The shared secret / password for the channel"),
36701
+ orgId: import_zod16.z.string().min(1).optional().describe(
36469
36702
  "Org_ID \u2014 the 3rd credential for a Team (business) channel. Provide it for team channels; omit for free channels."
36470
36703
  )
36471
36704
  },
@@ -36584,11 +36817,11 @@ function registerJoinSessionTool(server) {
36584
36817
  }
36585
36818
  );
36586
36819
  }
36587
- var import_zod15, UUID_V4_RE2;
36820
+ var import_zod16, UUID_V4_RE2;
36588
36821
  var init_join_session = __esm({
36589
36822
  "src/tools/join-session.ts"() {
36590
36823
  "use strict";
36591
- import_zod15 = __toESM(require_zod(), 1);
36824
+ import_zod16 = __toESM(require_zod(), 1);
36592
36825
  init_config();
36593
36826
  init_errors4();
36594
36827
  init_credential_store();
@@ -36652,12 +36885,12 @@ function registerSetupMailTool(server) {
36652
36885
  title: "Configure this agent's mailbox",
36653
36886
  description: "Store the agent's mailbox address + password (from the admin Mail panel) locally so cogent_send_mail and cogent_fetch_mail can use them. Hosts default to mail.cogent.tools (IMAP 993 / SMTP 465).",
36654
36887
  inputSchema: {
36655
- address: import_zod16.z.string().describe("Full mailbox address, e.g. claude-agent-backend@mail.cogent.tools"),
36656
- password: import_zod16.z.string().describe("Mailbox password (shown once in the admin Mail panel on create/rotate)"),
36657
- imapHost: import_zod16.z.string().optional().describe(`IMAP host (default ${DEFAULT_MAIL_HOST})`),
36658
- imapPort: import_zod16.z.number().int().positive().optional().describe("IMAP port (default 993)"),
36659
- smtpHost: import_zod16.z.string().optional().describe(`SMTP host (default ${DEFAULT_MAIL_HOST})`),
36660
- smtpPort: import_zod16.z.number().int().positive().optional().describe("SMTP submission port (default 465)")
36888
+ address: import_zod17.z.string().describe("Full mailbox address, e.g. claude-agent-backend@mail.cogent.tools"),
36889
+ password: import_zod17.z.string().describe("Mailbox password (shown once in the admin Mail panel on create/rotate)"),
36890
+ imapHost: import_zod17.z.string().optional().describe(`IMAP host (default ${DEFAULT_MAIL_HOST})`),
36891
+ imapPort: import_zod17.z.number().int().positive().optional().describe("IMAP port (default 993)"),
36892
+ smtpHost: import_zod17.z.string().optional().describe(`SMTP host (default ${DEFAULT_MAIL_HOST})`),
36893
+ smtpPort: import_zod17.z.number().int().positive().optional().describe("SMTP submission port (default 465)")
36661
36894
  },
36662
36895
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false }
36663
36896
  },
@@ -36681,11 +36914,11 @@ function registerSetupMailTool(server) {
36681
36914
  }
36682
36915
  );
36683
36916
  }
36684
- var import_zod16, DEFAULT_MAIL_HOST;
36917
+ var import_zod17, DEFAULT_MAIL_HOST;
36685
36918
  var init_setup_mail = __esm({
36686
36919
  "src/tools/setup-mail.ts"() {
36687
36920
  "use strict";
36688
- import_zod16 = __toESM(require_zod(), 1);
36921
+ import_zod17 = __toESM(require_zod(), 1);
36689
36922
  init_errors4();
36690
36923
  init_mail_credential_store();
36691
36924
  init_validate();
@@ -36694,13 +36927,13 @@ var init_setup_mail = __esm({
36694
36927
  });
36695
36928
 
36696
36929
  // src/mail/mail-sender.ts
36697
- import fs16 from "node:fs/promises";
36698
- import path17 from "node:path";
36930
+ import fs17 from "node:fs/promises";
36931
+ import path18 from "node:path";
36699
36932
  async function buildAndSendMail(sender, creds, params) {
36700
36933
  const attachments = [];
36701
36934
  for (const p of params.attachmentPaths ?? []) {
36702
- const content = await fs16.readFile(p);
36703
- attachments.push({ filename: path17.basename(p), content });
36935
+ const content = await fs17.readFile(p);
36936
+ attachments.push({ filename: path18.basename(p), content });
36704
36937
  }
36705
36938
  const { messageId } = await sender.send({
36706
36939
  from: creds.address,
@@ -36776,10 +37009,10 @@ function registerSendMailTool(server, deps = {}) {
36776
37009
  title: "Send an email from this agent's mailbox",
36777
37010
  description: "Send an email (with optional file attachments) from this agent's Cogent mailbox to another address. Requires cogent_setup_mail to have stored the mailbox credentials first.",
36778
37011
  inputSchema: {
36779
- to: import_zod17.z.string().describe("Recipient email address, e.g. other-agent-backend@mail.cogent.tools"),
36780
- subject: import_zod17.z.string().describe("Email subject"),
36781
- body: import_zod17.z.string().describe("Plain-text email body"),
36782
- attachments: import_zod17.z.array(import_zod17.z.string()).optional().describe("Optional local file paths to attach (each is read and attached by basename)")
37012
+ to: import_zod18.z.string().describe("Recipient email address, e.g. other-agent-backend@mail.cogent.tools"),
37013
+ subject: import_zod18.z.string().describe("Email subject"),
37014
+ body: import_zod18.z.string().describe("Plain-text email body"),
37015
+ attachments: import_zod18.z.array(import_zod18.z.string()).optional().describe("Optional local file paths to attach (each is read and attached by basename)")
36783
37016
  },
36784
37017
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }
36785
37018
  },
@@ -36793,7 +37026,7 @@ function registerSendMailTool(server, deps = {}) {
36793
37026
  new BridgeError(
36794
37027
  "INVALID_INPUT" /* INVALID_INPUT */,
36795
37028
  "No mailbox is configured for this agent",
36796
- "Run cogent_setup_mail with the address + password from the admin Mail panel first"
37029
+ MAIL_NOT_CONFIGURED_HINT
36797
37030
  )
36798
37031
  );
36799
37032
  }
@@ -36814,11 +37047,11 @@ function registerSendMailTool(server, deps = {}) {
36814
37047
  }
36815
37048
  );
36816
37049
  }
36817
- var import_zod17;
37050
+ var import_zod18;
36818
37051
  var init_send_mail = __esm({
36819
37052
  "src/tools/send-mail.ts"() {
36820
37053
  "use strict";
36821
- import_zod17 = __toESM(require_zod(), 1);
37054
+ import_zod18 = __toESM(require_zod(), 1);
36822
37055
  init_errors4();
36823
37056
  init_mail_credential_store();
36824
37057
  init_mail_sender();
@@ -36828,16 +37061,16 @@ var init_send_mail = __esm({
36828
37061
  });
36829
37062
 
36830
37063
  // src/mail/mail-fetcher.ts
36831
- import fs17 from "node:fs/promises";
36832
- import path18 from "node:path";
37064
+ import fs18 from "node:fs/promises";
37065
+ import path19 from "node:path";
36833
37066
  async function saveAttachments(attachments, downloadDir) {
36834
37067
  if (attachments.length === 0) return [];
36835
- await fs17.mkdir(downloadDir, { recursive: true });
37068
+ await fs18.mkdir(downloadDir, { recursive: true });
36836
37069
  const saved = [];
36837
37070
  for (const a of attachments) {
36838
- const name = path18.basename(a.filename) || "attachment";
36839
- const savedPath = path18.join(downloadDir, name);
36840
- await fs17.writeFile(savedPath, a.content);
37071
+ const name = path19.basename(a.filename) || "attachment";
37072
+ const savedPath = path19.join(downloadDir, name);
37073
+ await fs18.writeFile(savedPath, a.content);
36841
37074
  saved.push({ filename: name, savedPath, size: a.content.length });
36842
37075
  }
36843
37076
  return saved;
@@ -36968,8 +37201,8 @@ var init_mail_fetcher = __esm({
36968
37201
  });
36969
37202
 
36970
37203
  // src/tools/fetch-mail.ts
36971
- import os12 from "node:os";
36972
- import path19 from "node:path";
37204
+ import os13 from "node:os";
37205
+ import path20 from "node:path";
36973
37206
  function registerFetchMailTool(server, deps = {}) {
36974
37207
  const makeFetcher = deps.fetcherFactory ?? ((creds) => new ImapflowMailFetcher(creds));
36975
37208
  server.registerTool(
@@ -36978,11 +37211,11 @@ function registerFetchMailTool(server, deps = {}) {
36978
37211
  title: "Read this agent's mailbox",
36979
37212
  description: "List messages in this agent's Cogent mailbox, or fetch one message (text + attachments saved locally) by uid. Requires cogent_setup_mail to have stored the mailbox credentials.",
36980
37213
  inputSchema: {
36981
- action: import_zod18.z.enum(["list", "fetch"]).optional().describe("'list' (default) or 'fetch' one message"),
36982
- uid: import_zod18.z.number().int().positive().optional().describe("Message uid to fetch (required when action='fetch')"),
36983
- unreadOnly: import_zod18.z.boolean().optional().describe("List only unread messages (default false)"),
36984
- limit: import_zod18.z.number().int().positive().optional().describe("Max messages to list (default 25)"),
36985
- downloadDir: import_zod18.z.string().optional().describe(`Directory to save fetched attachments (default ${DEFAULT_DOWNLOAD_DIR})`)
37214
+ action: import_zod19.z.enum(["list", "fetch"]).optional().describe("'list' (default) or 'fetch' one message"),
37215
+ uid: import_zod19.z.number().int().positive().optional().describe("Message uid to fetch (required when action='fetch')"),
37216
+ unreadOnly: import_zod19.z.boolean().optional().describe("List only unread messages (default false)"),
37217
+ limit: import_zod19.z.number().int().positive().optional().describe("Max messages to list (default 25)"),
37218
+ downloadDir: import_zod19.z.string().optional().describe(`Directory to save fetched attachments (default ${DEFAULT_DOWNLOAD_DIR})`)
36986
37219
  },
36987
37220
  annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
36988
37221
  },
@@ -36994,7 +37227,7 @@ function registerFetchMailTool(server, deps = {}) {
36994
37227
  new BridgeError(
36995
37228
  "INVALID_INPUT" /* INVALID_INPUT */,
36996
37229
  "No mailbox is configured for this agent",
36997
- "Run cogent_setup_mail with the address + password from the admin Mail panel first"
37230
+ MAIL_NOT_CONFIGURED_HINT
36998
37231
  )
36999
37232
  );
37000
37233
  }
@@ -37021,17 +37254,17 @@ function registerFetchMailTool(server, deps = {}) {
37021
37254
  }
37022
37255
  );
37023
37256
  }
37024
- var import_zod18, DEFAULT_DOWNLOAD_DIR;
37257
+ var import_zod19, DEFAULT_DOWNLOAD_DIR;
37025
37258
  var init_fetch_mail = __esm({
37026
37259
  "src/tools/fetch-mail.ts"() {
37027
37260
  "use strict";
37028
- import_zod18 = __toESM(require_zod(), 1);
37261
+ import_zod19 = __toESM(require_zod(), 1);
37029
37262
  init_errors4();
37030
37263
  init_mail_credential_store();
37031
37264
  init_mail_fetcher();
37032
37265
  init_auth_error();
37033
37266
  init_validate();
37034
- DEFAULT_DOWNLOAD_DIR = path19.join(os12.homedir(), ".cogent", "mail-downloads");
37267
+ DEFAULT_DOWNLOAD_DIR = path20.join(os13.homedir(), ".cogent", "mail-downloads");
37035
37268
  }
37036
37269
  });
37037
37270
 
@@ -37131,6 +37364,7 @@ async function main() {
37131
37364
  registerListPeersTool(server);
37132
37365
  registerGetHistoryTool(server);
37133
37366
  registerHealthCheckTool(server);
37367
+ registerWakeLogTool(server);
37134
37368
  registerCreateSessionTool(server);
37135
37369
  registerJoinSessionTool(server);
37136
37370
  registerSetupMailTool(server);
@@ -37203,6 +37437,7 @@ var init_index = __esm({
37203
37437
  init_get_history();
37204
37438
  init_deregister_peer();
37205
37439
  init_health_check2();
37440
+ init_wake_log2();
37206
37441
  init_create_session();
37207
37442
  init_join_session();
37208
37443
  init_setup_mail();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@essentialai/cogent-bridge-bundled",
3
- "version": "3.22.0",
3
+ "version": "3.23.1",
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": {