@askexenow/exe-os 0.9.13 → 0.9.15

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 (70) hide show
  1. package/dist/bin/backfill-conversations.js +31 -4
  2. package/dist/bin/backfill-responses.js +31 -4
  3. package/dist/bin/backfill-vectors.js +25 -4
  4. package/dist/bin/cleanup-stale-review-tasks.js +1 -1
  5. package/dist/bin/cli.js +55 -8
  6. package/dist/bin/exe-assign.js +31 -4
  7. package/dist/bin/exe-boot.js +25 -4
  8. package/dist/bin/exe-dispatch.js +1 -1
  9. package/dist/bin/exe-doctor.js +1 -1
  10. package/dist/bin/exe-export-behaviors.js +1 -1
  11. package/dist/bin/exe-forget.js +1 -1
  12. package/dist/bin/exe-gateway.js +447 -21
  13. package/dist/bin/exe-heartbeat.js +1 -1
  14. package/dist/bin/exe-kill.js +1 -1
  15. package/dist/bin/exe-launch-agent.js +1 -1
  16. package/dist/bin/exe-link.js +31 -4
  17. package/dist/bin/exe-pending-messages.js +1 -1
  18. package/dist/bin/exe-pending-notifications.js +1 -1
  19. package/dist/bin/exe-pending-reviews.js +1 -1
  20. package/dist/bin/exe-rename.js +31 -4
  21. package/dist/bin/exe-review.js +1 -1
  22. package/dist/bin/exe-search.js +31 -4
  23. package/dist/bin/exe-session-cleanup.js +25 -4
  24. package/dist/bin/exe-start-codex.js +1 -1
  25. package/dist/bin/exe-start-opencode.js +1 -1
  26. package/dist/bin/exe-status.js +1 -1
  27. package/dist/bin/exe-team.js +1 -1
  28. package/dist/bin/git-sweep.js +25 -4
  29. package/dist/bin/graph-backfill.js +1 -1
  30. package/dist/bin/graph-export.js +1 -1
  31. package/dist/bin/scan-tasks.js +25 -4
  32. package/dist/bin/setup.js +46 -8
  33. package/dist/bin/shard-migrate.js +1 -1
  34. package/dist/bin/wiki-sync.js +1 -1
  35. package/dist/gateway/index.js +128 -125
  36. package/dist/hooks/bug-report-worker.js +1 -1
  37. package/dist/hooks/codex-stop-task-finalizer.js +1 -1
  38. package/dist/hooks/commit-complete.js +25 -4
  39. package/dist/hooks/error-recall.js +31 -4
  40. package/dist/hooks/ingest-worker.js +25 -4
  41. package/dist/hooks/ingest.js +1 -1
  42. package/dist/hooks/instructions-loaded.js +31 -4
  43. package/dist/hooks/notification.js +31 -4
  44. package/dist/hooks/post-compact.js +31 -4
  45. package/dist/hooks/pre-compact.js +25 -4
  46. package/dist/hooks/pre-tool-use.js +31 -4
  47. package/dist/hooks/prompt-ingest-worker.js +25 -4
  48. package/dist/hooks/prompt-submit.js +25 -4
  49. package/dist/hooks/response-ingest-worker.js +25 -4
  50. package/dist/hooks/session-end.js +25 -4
  51. package/dist/hooks/session-start.js +31 -4
  52. package/dist/hooks/stop.js +25 -4
  53. package/dist/hooks/subagent-stop.js +31 -4
  54. package/dist/hooks/summary-worker.js +25 -4
  55. package/dist/index.js +128 -125
  56. package/dist/lib/cloud-sync.js +31 -4
  57. package/dist/lib/database.js +31 -4
  58. package/dist/lib/db-daemon-client.js +31 -3
  59. package/dist/lib/db.js +31 -4
  60. package/dist/lib/device-registry.js +31 -4
  61. package/dist/lib/embedder.js +30 -3
  62. package/dist/lib/exe-daemon-client.js +31 -3
  63. package/dist/lib/exe-daemon.js +1969 -156
  64. package/dist/lib/hybrid-search.js +31 -4
  65. package/dist/lib/schedules.js +1 -1
  66. package/dist/lib/store.js +1 -1
  67. package/dist/mcp/server.js +25 -4
  68. package/dist/runtime/index.js +25 -4
  69. package/dist/tui/App.js +34 -4
  70. package/package.json +1 -1
@@ -1371,7 +1371,7 @@ async function ensureCompatibilityViews(prisma) {
1371
1371
  for (const mapping of VIEW_MAPPINGS) {
1372
1372
  const relation = mapping.source.replace(/"/g, "");
1373
1373
  const rows = await prisma.$queryRawUnsafe(
1374
- "SELECT to_regclass($1) AS regclass",
1374
+ "SELECT to_regclass($1)::text AS regclass",
1375
1375
  relation
1376
1376
  );
1377
1377
  if (!rows[0]?.regclass) {
@@ -2810,8 +2810,29 @@ function findPackageRoot() {
2810
2810
  }
2811
2811
  return null;
2812
2812
  }
2813
+ function getAvailableMemoryGB() {
2814
+ if (process.platform === "darwin") {
2815
+ try {
2816
+ const { execSync: execSync7 } = __require("child_process");
2817
+ const vmstat = execSync7("vm_stat", { encoding: "utf8" });
2818
+ const pageSize = 16384;
2819
+ const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
2820
+ const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
2821
+ const free = vmstat.match(/Pages free:\s+(\d+)/);
2822
+ const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
2823
+ const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
2824
+ const freePages = free ? parseInt(free[1], 10) : 0;
2825
+ const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
2826
+ const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
2827
+ return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
2828
+ } catch {
2829
+ return os4.freemem() / (1024 * 1024 * 1024);
2830
+ }
2831
+ }
2832
+ return os4.freemem() / (1024 * 1024 * 1024);
2833
+ }
2813
2834
  function spawnDaemon() {
2814
- const freeGB = os4.freemem() / (1024 * 1024 * 1024);
2835
+ const freeGB = getAvailableMemoryGB();
2815
2836
  const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
2816
2837
  if (totalGB <= 8) {
2817
2838
  process.stderr.write(
@@ -2820,9 +2841,9 @@ function spawnDaemon() {
2820
2841
  );
2821
2842
  return;
2822
2843
  }
2823
- if (totalGB <= 16 && freeGB < 4) {
2844
+ if (totalGB <= 16 && freeGB < 2) {
2824
2845
  process.stderr.write(
2825
- `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
2846
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
2826
2847
  `
2827
2848
  );
2828
2849
  return;
@@ -11163,6 +11184,7 @@ var WhatsAppAdapter = class {
11163
11184
  // src/gateway/adapters/signal.ts
11164
11185
  import { randomUUID as randomUUID6 } from "crypto";
11165
11186
  var DEFAULT_TIMEOUT_MS = 1e4;
11187
+ var POLL_INTERVAL_MS = 2e3;
11166
11188
  var SignalAdapter = class {
11167
11189
  platform = "signal";
11168
11190
  baseUrl = "";
@@ -11170,12 +11192,13 @@ var SignalAdapter = class {
11170
11192
  abortController = null;
11171
11193
  messageHandler = null;
11172
11194
  _connected = false;
11195
+ pollTimer = null;
11173
11196
  normalizeBaseUrl(url) {
11174
11197
  const trimmed = url.trim();
11175
11198
  if (/^https?:\/\//i.test(trimmed)) {
11176
11199
  return trimmed.replace(/\/+$/, "");
11177
11200
  }
11178
- return `https://${trimmed}`.replace(/\/+$/, "");
11201
+ return `http://${trimmed}`.replace(/\/+$/, "");
11179
11202
  }
11180
11203
  async connect(config2) {
11181
11204
  this.baseUrl = this.normalizeBaseUrl(
@@ -11185,12 +11208,12 @@ var SignalAdapter = class {
11185
11208
  const check = await this.healthCheck();
11186
11209
  if (!check.connected) {
11187
11210
  throw new Error(
11188
- `signal-cli daemon not reachable at ${this.baseUrl}. Start it with: signal-cli -a ${this.account} daemon --http`
11211
+ `signal-cli REST API not reachable at ${this.baseUrl}. Ensure bbernhard/signal-cli-rest-api container is running.`
11189
11212
  );
11190
11213
  }
11191
11214
  this._connected = true;
11192
11215
  this.abortController = new AbortController();
11193
- void this.startEventStream();
11216
+ void this.startPolling();
11194
11217
  void this.syncContacts().catch((err) => {
11195
11218
  console.error("[signal] Contact sync failed:", err);
11196
11219
  });
@@ -11201,6 +11224,10 @@ var SignalAdapter = class {
11201
11224
  async disconnect() {
11202
11225
  this.abortController?.abort();
11203
11226
  this.abortController = null;
11227
+ if (this.pollTimer) {
11228
+ clearTimeout(this.pollTimer);
11229
+ this.pollTimer = null;
11230
+ }
11204
11231
  this._connected = false;
11205
11232
  }
11206
11233
  onMessage(handler) {
@@ -11208,21 +11235,34 @@ var SignalAdapter = class {
11208
11235
  }
11209
11236
  async sendText(channelId, text, _options) {
11210
11237
  const isGroup = channelId.startsWith("group:");
11211
- const params = {
11238
+ const body = {
11212
11239
  message: text,
11213
- ...isGroup ? { groupId: channelId.slice("group:".length) } : { recipient: [channelId] }
11240
+ number: this.account,
11241
+ ...isGroup ? { recipients: [], group_id: channelId.slice("group:".length) } : { recipients: [channelId] }
11214
11242
  };
11215
- if (this.account) {
11216
- params.account = this.account;
11243
+ const res = await fetch(`${this.baseUrl}/v2/send`, {
11244
+ method: "POST",
11245
+ headers: { "Content-Type": "application/json" },
11246
+ body: JSON.stringify(body),
11247
+ signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS)
11248
+ });
11249
+ if (!res.ok) {
11250
+ const errText = await res.text().catch(() => "");
11251
+ throw new Error(`Signal send failed (${res.status}): ${errText}`);
11217
11252
  }
11218
- await this.rpcRequest("send", params);
11219
11253
  }
11220
11254
  async sendTyping(channelId) {
11221
11255
  try {
11222
11256
  const isGroup = channelId.startsWith("group:");
11223
- await this.rpcRequest("sendTyping", {
11224
- ...isGroup ? { groupId: channelId.slice("group:".length) } : { recipient: [channelId] },
11225
- ...this.account ? { account: this.account } : {}
11257
+ const endpoint = isGroup ? `${this.baseUrl}/v1/typing-indicator/${this.account}` : `${this.baseUrl}/v1/typing-indicator/${this.account}`;
11258
+ await fetch(endpoint, {
11259
+ method: "PUT",
11260
+ headers: { "Content-Type": "application/json" },
11261
+ body: JSON.stringify({
11262
+ recipient: isGroup ? void 0 : channelId,
11263
+ group_id: isGroup ? channelId.slice("group:".length) : void 0
11264
+ }),
11265
+ signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS)
11226
11266
  });
11227
11267
  } catch {
11228
11268
  }
@@ -11231,7 +11271,7 @@ var SignalAdapter = class {
11231
11271
  if (!this.baseUrl) return { connected: this._connected };
11232
11272
  const start = Date.now();
11233
11273
  try {
11234
- const res = await fetch(`${this.baseUrl}/api/v1/check`, {
11274
+ const res = await fetch(`${this.baseUrl}/v1/about`, {
11235
11275
  method: "GET",
11236
11276
  signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS)
11237
11277
  });
@@ -11245,96 +11285,48 @@ var SignalAdapter = class {
11245
11285
  return { connected: false };
11246
11286
  }
11247
11287
  }
11248
- async rpcRequest(method, params) {
11249
- const id = randomUUID6();
11250
- const res = await fetch(`${this.baseUrl}/api/v1/rpc`, {
11251
- method: "POST",
11252
- headers: { "Content-Type": "application/json" },
11253
- body: JSON.stringify({ jsonrpc: "2.0", method, params, id }),
11254
- signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS)
11255
- });
11256
- if (res.status === 201) return void 0;
11257
- const text = await res.text();
11258
- if (!text) throw new Error(`Signal RPC empty response (${res.status})`);
11259
- const parsed = JSON.parse(text);
11260
- if (parsed.error) {
11261
- throw new Error(
11262
- `Signal RPC ${parsed.error.code ?? "unknown"}: ${parsed.error.message ?? "error"}`
11263
- );
11264
- }
11265
- return parsed.result;
11266
- }
11267
- async startEventStream() {
11268
- const url = new URL(`${this.baseUrl}/api/v1/events`);
11269
- if (this.account) {
11270
- url.searchParams.set("account", this.account);
11271
- }
11288
+ async startPolling() {
11272
11289
  while (this.abortController && !this.abortController.signal.aborted) {
11273
11290
  try {
11274
- const res = await fetch(url, {
11275
- method: "GET",
11276
- headers: { Accept: "text/event-stream" },
11277
- signal: this.abortController.signal
11278
- });
11279
- if (!res.ok || !res.body) {
11280
- throw new Error(`Signal SSE failed (${res.status})`);
11281
- }
11282
- const reader = res.body.getReader();
11283
- const decoder = new TextDecoder();
11284
- let buffer = "";
11285
- let currentEvent = {};
11286
- const flushEvent = () => {
11287
- if (currentEvent.data) {
11288
- void this.handleSseEvent(currentEvent);
11289
- }
11290
- currentEvent = {};
11291
- };
11292
- while (true) {
11293
- const { value, done } = await reader.read();
11294
- if (done) break;
11295
- buffer += decoder.decode(value, { stream: true });
11296
- let lineEnd = buffer.indexOf("\n");
11297
- while (lineEnd !== -1) {
11298
- let line = buffer.slice(0, lineEnd);
11299
- buffer = buffer.slice(lineEnd + 1);
11300
- if (line.endsWith("\r")) line = line.slice(0, -1);
11301
- if (line === "") {
11302
- flushEvent();
11303
- } else if (!line.startsWith(":")) {
11304
- const colonIdx = line.indexOf(":");
11305
- if (colonIdx !== -1) {
11306
- const field = line.slice(0, colonIdx).trim();
11307
- const val = line.slice(colonIdx + 1).replace(/^ /, "");
11308
- if (field === "event") currentEvent.event = val;
11309
- else if (field === "data") {
11310
- currentEvent.data = currentEvent.data ? `${currentEvent.data}
11311
- ${val}` : val;
11312
- }
11313
- }
11314
- }
11315
- lineEnd = buffer.indexOf("\n");
11316
- }
11317
- }
11291
+ await this.pollMessages();
11318
11292
  } catch (err) {
11319
11293
  if (this.abortController?.signal.aborted) return;
11320
- console.error("[signal] SSE stream error, reconnecting in 5s:", err);
11321
- await new Promise((r) => setTimeout(r, 5e3));
11294
+ console.error("[signal] Poll error:", err);
11322
11295
  }
11296
+ await new Promise((resolve) => {
11297
+ this.pollTimer = setTimeout(resolve, POLL_INTERVAL_MS);
11298
+ });
11323
11299
  }
11324
11300
  }
11325
- async handleSseEvent(event) {
11326
- if (!event.data || !this.messageHandler) return;
11327
- let payload;
11328
- try {
11329
- payload = JSON.parse(event.data);
11330
- } catch {
11331
- return;
11301
+ async pollMessages() {
11302
+ if (!this.account || !this.messageHandler) return;
11303
+ const res = await fetch(
11304
+ `${this.baseUrl}/v1/receive/${encodeURIComponent(this.account)}`,
11305
+ {
11306
+ method: "GET",
11307
+ signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS)
11308
+ }
11309
+ );
11310
+ if (!res.ok) {
11311
+ if (res.status === 400) {
11312
+ return;
11313
+ }
11314
+ throw new Error(`Signal receive failed (${res.status})`);
11332
11315
  }
11333
- const envelope = payload.envelope;
11316
+ const entries = await res.json();
11317
+ if (!Array.isArray(entries) || entries.length === 0) return;
11318
+ for (const entry of entries) {
11319
+ await this.handleEntry(entry);
11320
+ }
11321
+ }
11322
+ async handleEntry(entry) {
11323
+ if (!this.messageHandler) return;
11324
+ const envelope = entry.envelope;
11334
11325
  if (!envelope) return;
11335
- const senderId = envelope.sourceNumber ?? envelope.sourceUuid ?? "";
11336
- if (envelope.reactionMessage) {
11337
- const rm = envelope.reactionMessage;
11326
+ const senderId = envelope.sourceNumber ?? envelope.source ?? envelope.sourceUuid ?? "";
11327
+ if (envelope.dataMessage?.reaction) {
11328
+ const rm = envelope.dataMessage.reaction;
11329
+ if (rm.isRemove) return;
11338
11330
  const normalized2 = {
11339
11331
  messageId: randomUUID6(),
11340
11332
  platform: "signal",
@@ -11346,11 +11338,11 @@ ${val}` : val;
11346
11338
  timestamp: new Date(
11347
11339
  envelope.timestamp ?? Date.now()
11348
11340
  ).toISOString(),
11349
- raw: payload,
11341
+ raw: entry,
11350
11342
  dataCategory: "reaction",
11351
11343
  reaction: {
11352
- emoji: rm.emoji,
11353
- targetMessageId: String(rm.targetTimestamp),
11344
+ emoji: rm.emoji ?? "",
11345
+ targetMessageId: String(rm.targetSentTimestamp ?? ""),
11354
11346
  reactedBy: senderId,
11355
11347
  timestamp: new Date(
11356
11348
  envelope.timestamp ?? Date.now()
@@ -11362,7 +11354,7 @@ ${val}` : val;
11362
11354
  }
11363
11355
  if (envelope.receiptMessage) {
11364
11356
  const rcpt = envelope.receiptMessage;
11365
- for (const ts2 of rcpt.timestamps) {
11357
+ for (const ts2 of rcpt.timestamps ?? []) {
11366
11358
  const normalized2 = {
11367
11359
  messageId: randomUUID6(),
11368
11360
  platform: "signal",
@@ -11374,11 +11366,11 @@ ${val}` : val;
11374
11366
  timestamp: new Date(
11375
11367
  envelope.timestamp ?? Date.now()
11376
11368
  ).toISOString(),
11377
- raw: payload,
11369
+ raw: entry,
11378
11370
  dataCategory: "read_receipt",
11379
11371
  readReceipt: {
11380
11372
  messageId: String(ts2),
11381
- status: rcpt.type === "read" ? "read" : "delivered",
11373
+ status: rcpt.type === "READ" ? "read" : "delivered",
11382
11374
  timestamp: new Date(
11383
11375
  envelope.timestamp ?? Date.now()
11384
11376
  ).toISOString(),
@@ -11392,6 +11384,7 @@ ${val}` : val;
11392
11384
  if (envelope.editMessage) {
11393
11385
  const em = envelope.editMessage;
11394
11386
  const dm2 = em.dataMessage;
11387
+ if (!dm2) return;
11395
11388
  const isGroup2 = !!dm2.groupInfo?.groupId;
11396
11389
  const normalized2 = {
11397
11390
  messageId: String(dm2.timestamp ?? randomUUID6()),
@@ -11404,11 +11397,11 @@ ${val}` : val;
11404
11397
  timestamp: new Date(
11405
11398
  envelope.timestamp ?? Date.now()
11406
11399
  ).toISOString(),
11407
- media: this.extractMedia(dm2),
11408
- raw: payload,
11400
+ media: this.extractMedia(dm2.attachments),
11401
+ raw: entry,
11409
11402
  dataCategory: "edit",
11410
11403
  replyTo: {
11411
- messageId: String(em.targetTimestamp),
11404
+ messageId: String(em.targetSentTimestamp ?? ""),
11412
11405
  text: "",
11413
11406
  senderId
11414
11407
  }
@@ -11430,13 +11423,13 @@ ${val}` : val;
11430
11423
  timestamp: new Date(
11431
11424
  envelope.timestamp ?? Date.now()
11432
11425
  ).toISOString(),
11433
- media: this.extractMedia(dm),
11426
+ media: this.extractMedia(dm.attachments),
11434
11427
  replyTo: dm.quote ? {
11435
11428
  messageId: String(dm.quote.id ?? ""),
11436
11429
  text: dm.quote.text ?? "",
11437
- senderId: dm.quote.authorNumber ?? ""
11430
+ senderId: dm.quote.author ?? ""
11438
11431
  } : void 0,
11439
- raw: payload,
11432
+ raw: entry,
11440
11433
  dataCategory: "message"
11441
11434
  };
11442
11435
  await this.emitMessage(normalized);
@@ -11449,12 +11442,15 @@ ${val}` : val;
11449
11442
  console.error("[signal] Message handler error:", err);
11450
11443
  }
11451
11444
  }
11452
- /** Import all Signal contacts via listContacts RPC */
11445
+ /** Import all Signal contacts */
11453
11446
  async syncContacts() {
11454
- if (!this.messageHandler) return;
11455
- const contacts = await this.rpcRequest("listContacts", {
11456
- ...this.account ? { account: this.account } : {}
11457
- });
11447
+ if (!this.messageHandler || !this.account) return;
11448
+ const res = await fetch(
11449
+ `${this.baseUrl}/v1/contacts/${encodeURIComponent(this.account)}`,
11450
+ { signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS) }
11451
+ );
11452
+ if (!res.ok) return;
11453
+ const contacts = await res.json();
11458
11454
  if (!Array.isArray(contacts)) return;
11459
11455
  for (const contact of contacts) {
11460
11456
  const phone = contact.number ?? "";
@@ -11481,12 +11477,15 @@ ${val}` : val;
11481
11477
  }
11482
11478
  console.log(`[signal] Synced ${contacts.length} contacts`);
11483
11479
  }
11484
- /** Import all Signal groups via listGroups RPC */
11480
+ /** Import all Signal groups */
11485
11481
  async syncGroups() {
11486
- if (!this.messageHandler) return;
11487
- const groups = await this.rpcRequest("listGroups", {
11488
- ...this.account ? { account: this.account } : {}
11489
- });
11482
+ if (!this.messageHandler || !this.account) return;
11483
+ const res = await fetch(
11484
+ `${this.baseUrl}/v1/groups/${encodeURIComponent(this.account)}`,
11485
+ { signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS) }
11486
+ );
11487
+ if (!res.ok) return;
11488
+ const groups = await res.json();
11490
11489
  if (!Array.isArray(groups)) return;
11491
11490
  for (const group of groups) {
11492
11491
  const normalized = {
@@ -11511,15 +11510,19 @@ ${val}` : val;
11511
11510
  }
11512
11511
  console.log(`[signal] Synced ${groups.length} groups`);
11513
11512
  }
11514
- extractMedia(dm) {
11515
- if (!dm.attachments?.length) return void 0;
11516
- return dm.attachments.map((att) => {
11513
+ extractMedia(attachments) {
11514
+ if (!attachments?.length) return void 0;
11515
+ return attachments.map((att) => {
11517
11516
  const ct = att.contentType ?? "";
11518
11517
  let type = "document";
11519
11518
  if (ct.startsWith("image/")) type = "image";
11520
11519
  else if (ct.startsWith("video/")) type = "video";
11521
11520
  else if (ct.startsWith("audio/")) type = "audio";
11522
- return { type, fileName: att.filename ?? void 0 };
11521
+ return {
11522
+ type,
11523
+ fileName: att.filename ?? void 0,
11524
+ url: att.id ? `${this.baseUrl}/v1/attachments/${att.id}` : void 0
11525
+ };
11523
11526
  });
11524
11527
  }
11525
11528
  };
@@ -12088,7 +12091,7 @@ import { promisify } from "util";
12088
12091
  import os6 from "os";
12089
12092
  import path9 from "path";
12090
12093
  var execFileAsync = promisify(execFile);
12091
- var POLL_INTERVAL_MS = 5e3;
12094
+ var POLL_INTERVAL_MS2 = 5e3;
12092
12095
  var MESSAGES_DB_PATH = path9.join(
12093
12096
  process.env.HOME ?? os6.homedir(),
12094
12097
  "Library/Messages/chat.db"
@@ -12125,7 +12128,7 @@ var IMessageAdapter = class {
12125
12128
  console.log("[imessage] Connected via AppleScript bridge");
12126
12129
  this.pollTimer = setInterval(() => {
12127
12130
  void this.pollMessages();
12128
- }, POLL_INTERVAL_MS);
12131
+ }, POLL_INTERVAL_MS2);
12129
12132
  }
12130
12133
  async disconnect() {
12131
12134
  if (this.pollTimer) {
@@ -1005,7 +1005,7 @@ async function ensureCompatibilityViews(prisma) {
1005
1005
  for (const mapping of VIEW_MAPPINGS) {
1006
1006
  const relation = mapping.source.replace(/"/g, "");
1007
1007
  const rows = await prisma.$queryRawUnsafe(
1008
- "SELECT to_regclass($1) AS regclass",
1008
+ "SELECT to_regclass($1)::text AS regclass",
1009
1009
  relation
1010
1010
  );
1011
1011
  if (!rows[0]?.regclass) {
@@ -678,7 +678,7 @@ async function ensureCompatibilityViews(prisma) {
678
678
  for (const mapping of VIEW_MAPPINGS) {
679
679
  const relation = mapping.source.replace(/"/g, "");
680
680
  const rows = await prisma.$queryRawUnsafe(
681
- "SELECT to_regclass($1) AS regclass",
681
+ "SELECT to_regclass($1)::text AS regclass",
682
682
  relation
683
683
  );
684
684
  if (!rows[0]?.regclass) {
@@ -1176,7 +1176,7 @@ async function ensureCompatibilityViews(prisma) {
1176
1176
  for (const mapping of VIEW_MAPPINGS) {
1177
1177
  const relation = mapping.source.replace(/"/g, "");
1178
1178
  const rows = await prisma.$queryRawUnsafe(
1179
- "SELECT to_regclass($1) AS regclass",
1179
+ "SELECT to_regclass($1)::text AS regclass",
1180
1180
  relation
1181
1181
  );
1182
1182
  if (!rows[0]?.regclass) {
@@ -1530,8 +1530,29 @@ function findPackageRoot() {
1530
1530
  }
1531
1531
  return null;
1532
1532
  }
1533
+ function getAvailableMemoryGB() {
1534
+ if (process.platform === "darwin") {
1535
+ try {
1536
+ const { execSync: execSync9 } = __require("child_process");
1537
+ const vmstat = execSync9("vm_stat", { encoding: "utf8" });
1538
+ const pageSize = 16384;
1539
+ const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1540
+ const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
1541
+ const free = vmstat.match(/Pages free:\s+(\d+)/);
1542
+ const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
1543
+ const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
1544
+ const freePages = free ? parseInt(free[1], 10) : 0;
1545
+ const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
1546
+ const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
1547
+ return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
1548
+ } catch {
1549
+ return os6.freemem() / (1024 * 1024 * 1024);
1550
+ }
1551
+ }
1552
+ return os6.freemem() / (1024 * 1024 * 1024);
1553
+ }
1533
1554
  function spawnDaemon() {
1534
- const freeGB = os6.freemem() / (1024 * 1024 * 1024);
1555
+ const freeGB = getAvailableMemoryGB();
1535
1556
  const totalGB = os6.totalmem() / (1024 * 1024 * 1024);
1536
1557
  if (totalGB <= 8) {
1537
1558
  process.stderr.write(
@@ -1540,9 +1561,9 @@ function spawnDaemon() {
1540
1561
  );
1541
1562
  return;
1542
1563
  }
1543
- if (totalGB <= 16 && freeGB < 4) {
1564
+ if (totalGB <= 16 && freeGB < 2) {
1544
1565
  process.stderr.write(
1545
- `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
1566
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
1546
1567
  `
1547
1568
  );
1548
1569
  return;
@@ -1,5 +1,11 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
4
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
5
+ }) : x)(function(x) {
6
+ if (typeof require !== "undefined") return require.apply(this, arguments);
7
+ throw Error('Dynamic require of "' + x + '" is not supported');
8
+ });
3
9
  var __esm = (fn, res) => function __init() {
4
10
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
5
11
  };
@@ -723,7 +729,7 @@ async function ensureCompatibilityViews(prisma) {
723
729
  for (const mapping of VIEW_MAPPINGS) {
724
730
  const relation = mapping.source.replace(/"/g, "");
725
731
  const rows = await prisma.$queryRawUnsafe(
726
- "SELECT to_regclass($1) AS regclass",
732
+ "SELECT to_regclass($1)::text AS regclass",
727
733
  relation
728
734
  );
729
735
  if (!rows[0]?.regclass) {
@@ -3562,8 +3568,29 @@ function findPackageRoot() {
3562
3568
  }
3563
3569
  return null;
3564
3570
  }
3571
+ function getAvailableMemoryGB() {
3572
+ if (process.platform === "darwin") {
3573
+ try {
3574
+ const { execSync: execSync6 } = __require("child_process");
3575
+ const vmstat = execSync6("vm_stat", { encoding: "utf8" });
3576
+ const pageSize = 16384;
3577
+ const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
3578
+ const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
3579
+ const free = vmstat.match(/Pages free:\s+(\d+)/);
3580
+ const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
3581
+ const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
3582
+ const freePages = free ? parseInt(free[1], 10) : 0;
3583
+ const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
3584
+ const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
3585
+ return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
3586
+ } catch {
3587
+ return os5.freemem() / (1024 * 1024 * 1024);
3588
+ }
3589
+ }
3590
+ return os5.freemem() / (1024 * 1024 * 1024);
3591
+ }
3565
3592
  function spawnDaemon() {
3566
- const freeGB = os5.freemem() / (1024 * 1024 * 1024);
3593
+ const freeGB = getAvailableMemoryGB();
3567
3594
  const totalGB = os5.totalmem() / (1024 * 1024 * 1024);
3568
3595
  if (totalGB <= 8) {
3569
3596
  process.stderr.write(
@@ -3572,9 +3599,9 @@ function spawnDaemon() {
3572
3599
  );
3573
3600
  return;
3574
3601
  }
3575
- if (totalGB <= 16 && freeGB < 4) {
3602
+ if (totalGB <= 16 && freeGB < 2) {
3576
3603
  process.stderr.write(
3577
- `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
3604
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
3578
3605
  `
3579
3606
  );
3580
3607
  return;
@@ -848,7 +848,7 @@ async function ensureCompatibilityViews(prisma) {
848
848
  for (const mapping of VIEW_MAPPINGS) {
849
849
  const relation = mapping.source.replace(/"/g, "");
850
850
  const rows = await prisma.$queryRawUnsafe(
851
- "SELECT to_regclass($1) AS regclass",
851
+ "SELECT to_regclass($1)::text AS regclass",
852
852
  relation
853
853
  );
854
854
  if (!rows[0]?.regclass) {
@@ -1202,8 +1202,29 @@ function findPackageRoot() {
1202
1202
  }
1203
1203
  return null;
1204
1204
  }
1205
+ function getAvailableMemoryGB() {
1206
+ if (process.platform === "darwin") {
1207
+ try {
1208
+ const { execSync: execSync8 } = __require("child_process");
1209
+ const vmstat = execSync8("vm_stat", { encoding: "utf8" });
1210
+ const pageSize = 16384;
1211
+ const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1212
+ const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
1213
+ const free = vmstat.match(/Pages free:\s+(\d+)/);
1214
+ const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
1215
+ const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
1216
+ const freePages = free ? parseInt(free[1], 10) : 0;
1217
+ const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
1218
+ const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
1219
+ return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
1220
+ } catch {
1221
+ return os4.freemem() / (1024 * 1024 * 1024);
1222
+ }
1223
+ }
1224
+ return os4.freemem() / (1024 * 1024 * 1024);
1225
+ }
1205
1226
  function spawnDaemon() {
1206
- const freeGB = os4.freemem() / (1024 * 1024 * 1024);
1227
+ const freeGB = getAvailableMemoryGB();
1207
1228
  const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
1208
1229
  if (totalGB <= 8) {
1209
1230
  process.stderr.write(
@@ -1212,9 +1233,9 @@ function spawnDaemon() {
1212
1233
  );
1213
1234
  return;
1214
1235
  }
1215
- if (totalGB <= 16 && freeGB < 4) {
1236
+ if (totalGB <= 16 && freeGB < 2) {
1216
1237
  process.stderr.write(
1217
- `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
1238
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
1218
1239
  `
1219
1240
  );
1220
1241
  return;
@@ -1046,7 +1046,7 @@ async function ensureCompatibilityViews(prisma) {
1046
1046
  for (const mapping of VIEW_MAPPINGS) {
1047
1047
  const relation = mapping.source.replace(/"/g, "");
1048
1048
  const rows = await prisma.$queryRawUnsafe(
1049
- "SELECT to_regclass($1) AS regclass",
1049
+ "SELECT to_regclass($1)::text AS regclass",
1050
1050
  relation
1051
1051
  );
1052
1052
  if (!rows[0]?.regclass) {