@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.
- package/dist/bin/backfill-conversations.js +31 -4
- package/dist/bin/backfill-responses.js +31 -4
- package/dist/bin/backfill-vectors.js +25 -4
- package/dist/bin/cleanup-stale-review-tasks.js +1 -1
- package/dist/bin/cli.js +55 -8
- package/dist/bin/exe-assign.js +31 -4
- package/dist/bin/exe-boot.js +25 -4
- package/dist/bin/exe-dispatch.js +1 -1
- package/dist/bin/exe-doctor.js +1 -1
- package/dist/bin/exe-export-behaviors.js +1 -1
- package/dist/bin/exe-forget.js +1 -1
- package/dist/bin/exe-gateway.js +447 -21
- package/dist/bin/exe-heartbeat.js +1 -1
- package/dist/bin/exe-kill.js +1 -1
- package/dist/bin/exe-launch-agent.js +1 -1
- package/dist/bin/exe-link.js +31 -4
- package/dist/bin/exe-pending-messages.js +1 -1
- package/dist/bin/exe-pending-notifications.js +1 -1
- package/dist/bin/exe-pending-reviews.js +1 -1
- package/dist/bin/exe-rename.js +31 -4
- package/dist/bin/exe-review.js +1 -1
- package/dist/bin/exe-search.js +31 -4
- package/dist/bin/exe-session-cleanup.js +25 -4
- package/dist/bin/exe-start-codex.js +1 -1
- package/dist/bin/exe-start-opencode.js +1 -1
- package/dist/bin/exe-status.js +1 -1
- package/dist/bin/exe-team.js +1 -1
- package/dist/bin/git-sweep.js +25 -4
- package/dist/bin/graph-backfill.js +1 -1
- package/dist/bin/graph-export.js +1 -1
- package/dist/bin/scan-tasks.js +25 -4
- package/dist/bin/setup.js +46 -8
- package/dist/bin/shard-migrate.js +1 -1
- package/dist/bin/wiki-sync.js +1 -1
- package/dist/gateway/index.js +128 -125
- package/dist/hooks/bug-report-worker.js +1 -1
- package/dist/hooks/codex-stop-task-finalizer.js +1 -1
- package/dist/hooks/commit-complete.js +25 -4
- package/dist/hooks/error-recall.js +31 -4
- package/dist/hooks/ingest-worker.js +25 -4
- package/dist/hooks/ingest.js +1 -1
- package/dist/hooks/instructions-loaded.js +31 -4
- package/dist/hooks/notification.js +31 -4
- package/dist/hooks/post-compact.js +31 -4
- package/dist/hooks/pre-compact.js +25 -4
- package/dist/hooks/pre-tool-use.js +31 -4
- package/dist/hooks/prompt-ingest-worker.js +25 -4
- package/dist/hooks/prompt-submit.js +25 -4
- package/dist/hooks/response-ingest-worker.js +25 -4
- package/dist/hooks/session-end.js +25 -4
- package/dist/hooks/session-start.js +31 -4
- package/dist/hooks/stop.js +25 -4
- package/dist/hooks/subagent-stop.js +31 -4
- package/dist/hooks/summary-worker.js +25 -4
- package/dist/index.js +128 -125
- package/dist/lib/cloud-sync.js +31 -4
- package/dist/lib/database.js +31 -4
- package/dist/lib/db-daemon-client.js +31 -3
- package/dist/lib/db.js +31 -4
- package/dist/lib/device-registry.js +31 -4
- package/dist/lib/embedder.js +30 -3
- package/dist/lib/exe-daemon-client.js +31 -3
- package/dist/lib/exe-daemon.js +1969 -156
- package/dist/lib/hybrid-search.js +31 -4
- package/dist/lib/schedules.js +1 -1
- package/dist/lib/store.js +1 -1
- package/dist/mcp/server.js +25 -4
- package/dist/runtime/index.js +25 -4
- package/dist/tui/App.js +34 -4
- package/package.json +1 -1
package/dist/gateway/index.js
CHANGED
|
@@ -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 =
|
|
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 <
|
|
2844
|
+
if (totalGB <= 16 && freeGB < 2) {
|
|
2824
2845
|
process.stderr.write(
|
|
2825
|
-
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB
|
|
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 `
|
|
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
|
|
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.
|
|
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
|
|
11238
|
+
const body = {
|
|
11212
11239
|
message: text,
|
|
11213
|
-
|
|
11240
|
+
number: this.account,
|
|
11241
|
+
...isGroup ? { recipients: [], group_id: channelId.slice("group:".length) } : { recipients: [channelId] }
|
|
11214
11242
|
};
|
|
11215
|
-
|
|
11216
|
-
|
|
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
|
-
|
|
11224
|
-
|
|
11225
|
-
|
|
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}/
|
|
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
|
|
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
|
-
|
|
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]
|
|
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
|
|
11326
|
-
if (!
|
|
11327
|
-
|
|
11328
|
-
|
|
11329
|
-
|
|
11330
|
-
|
|
11331
|
-
|
|
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
|
|
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.
|
|
11337
|
-
const rm = envelope.
|
|
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:
|
|
11341
|
+
raw: entry,
|
|
11350
11342
|
dataCategory: "reaction",
|
|
11351
11343
|
reaction: {
|
|
11352
|
-
emoji: rm.emoji,
|
|
11353
|
-
targetMessageId: String(rm.
|
|
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:
|
|
11369
|
+
raw: entry,
|
|
11378
11370
|
dataCategory: "read_receipt",
|
|
11379
11371
|
readReceipt: {
|
|
11380
11372
|
messageId: String(ts2),
|
|
11381
|
-
status: rcpt.type === "
|
|
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:
|
|
11400
|
+
media: this.extractMedia(dm2.attachments),
|
|
11401
|
+
raw: entry,
|
|
11409
11402
|
dataCategory: "edit",
|
|
11410
11403
|
replyTo: {
|
|
11411
|
-
messageId: String(em.
|
|
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.
|
|
11430
|
+
senderId: dm.quote.author ?? ""
|
|
11438
11431
|
} : void 0,
|
|
11439
|
-
raw:
|
|
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
|
|
11445
|
+
/** Import all Signal contacts */
|
|
11453
11446
|
async syncContacts() {
|
|
11454
|
-
if (!this.messageHandler) return;
|
|
11455
|
-
const
|
|
11456
|
-
|
|
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
|
|
11480
|
+
/** Import all Signal groups */
|
|
11485
11481
|
async syncGroups() {
|
|
11486
|
-
if (!this.messageHandler) return;
|
|
11487
|
-
const
|
|
11488
|
-
|
|
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(
|
|
11515
|
-
if (!
|
|
11516
|
-
return
|
|
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 {
|
|
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
|
|
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
|
-
},
|
|
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 =
|
|
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 <
|
|
1564
|
+
if (totalGB <= 16 && freeGB < 2) {
|
|
1544
1565
|
process.stderr.write(
|
|
1545
|
-
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB
|
|
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 =
|
|
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 <
|
|
3602
|
+
if (totalGB <= 16 && freeGB < 2) {
|
|
3576
3603
|
process.stderr.write(
|
|
3577
|
-
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB
|
|
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 =
|
|
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 <
|
|
1236
|
+
if (totalGB <= 16 && freeGB < 2) {
|
|
1216
1237
|
process.stderr.write(
|
|
1217
|
-
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB
|
|
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;
|
package/dist/hooks/ingest.js
CHANGED
|
@@ -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) {
|