@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
|
@@ -2,6 +2,12 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
4
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
6
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
7
|
+
}) : x)(function(x) {
|
|
8
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
9
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
10
|
+
});
|
|
5
11
|
var __esm = (fn, res) => function __init() {
|
|
6
12
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
7
13
|
};
|
|
@@ -951,7 +957,7 @@ async function ensureCompatibilityViews(prisma) {
|
|
|
951
957
|
for (const mapping of VIEW_MAPPINGS) {
|
|
952
958
|
const relation = mapping.source.replace(/"/g, "");
|
|
953
959
|
const rows = await prisma.$queryRawUnsafe(
|
|
954
|
-
"SELECT to_regclass($1) AS regclass",
|
|
960
|
+
"SELECT to_regclass($1)::text AS regclass",
|
|
955
961
|
relation
|
|
956
962
|
);
|
|
957
963
|
if (!rows[0]?.regclass) {
|
|
@@ -1305,8 +1311,29 @@ function findPackageRoot() {
|
|
|
1305
1311
|
}
|
|
1306
1312
|
return null;
|
|
1307
1313
|
}
|
|
1314
|
+
function getAvailableMemoryGB() {
|
|
1315
|
+
if (process.platform === "darwin") {
|
|
1316
|
+
try {
|
|
1317
|
+
const { execSync: execSync5 } = __require("child_process");
|
|
1318
|
+
const vmstat = execSync5("vm_stat", { encoding: "utf8" });
|
|
1319
|
+
const pageSize = 16384;
|
|
1320
|
+
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1321
|
+
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
1322
|
+
const free = vmstat.match(/Pages free:\s+(\d+)/);
|
|
1323
|
+
const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
|
|
1324
|
+
const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
|
|
1325
|
+
const freePages = free ? parseInt(free[1], 10) : 0;
|
|
1326
|
+
const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
|
|
1327
|
+
const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
|
|
1328
|
+
return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
|
|
1329
|
+
} catch {
|
|
1330
|
+
return os6.freemem() / (1024 * 1024 * 1024);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
return os6.freemem() / (1024 * 1024 * 1024);
|
|
1334
|
+
}
|
|
1308
1335
|
function spawnDaemon() {
|
|
1309
|
-
const freeGB =
|
|
1336
|
+
const freeGB = getAvailableMemoryGB();
|
|
1310
1337
|
const totalGB = os6.totalmem() / (1024 * 1024 * 1024);
|
|
1311
1338
|
if (totalGB <= 8) {
|
|
1312
1339
|
process.stderr.write(
|
|
@@ -1315,9 +1342,9 @@ function spawnDaemon() {
|
|
|
1315
1342
|
);
|
|
1316
1343
|
return;
|
|
1317
1344
|
}
|
|
1318
|
-
if (totalGB <= 16 && freeGB <
|
|
1345
|
+
if (totalGB <= 16 && freeGB < 2) {
|
|
1319
1346
|
process.stderr.write(
|
|
1320
|
-
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB
|
|
1347
|
+
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
|
|
1321
1348
|
`
|
|
1322
1349
|
);
|
|
1323
1350
|
return;
|
|
@@ -799,7 +799,7 @@ async function ensureCompatibilityViews(prisma) {
|
|
|
799
799
|
for (const mapping of VIEW_MAPPINGS) {
|
|
800
800
|
const relation = mapping.source.replace(/"/g, "");
|
|
801
801
|
const rows = await prisma.$queryRawUnsafe(
|
|
802
|
-
"SELECT to_regclass($1) AS regclass",
|
|
802
|
+
"SELECT to_regclass($1)::text AS regclass",
|
|
803
803
|
relation
|
|
804
804
|
);
|
|
805
805
|
if (!rows[0]?.regclass) {
|
|
@@ -1153,8 +1153,29 @@ function findPackageRoot() {
|
|
|
1153
1153
|
}
|
|
1154
1154
|
return null;
|
|
1155
1155
|
}
|
|
1156
|
+
function getAvailableMemoryGB() {
|
|
1157
|
+
if (process.platform === "darwin") {
|
|
1158
|
+
try {
|
|
1159
|
+
const { execSync: execSync5 } = __require("child_process");
|
|
1160
|
+
const vmstat = execSync5("vm_stat", { encoding: "utf8" });
|
|
1161
|
+
const pageSize = 16384;
|
|
1162
|
+
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1163
|
+
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
1164
|
+
const free = vmstat.match(/Pages free:\s+(\d+)/);
|
|
1165
|
+
const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
|
|
1166
|
+
const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
|
|
1167
|
+
const freePages = free ? parseInt(free[1], 10) : 0;
|
|
1168
|
+
const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
|
|
1169
|
+
const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
|
|
1170
|
+
return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
|
|
1171
|
+
} catch {
|
|
1172
|
+
return os4.freemem() / (1024 * 1024 * 1024);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
return os4.freemem() / (1024 * 1024 * 1024);
|
|
1176
|
+
}
|
|
1156
1177
|
function spawnDaemon() {
|
|
1157
|
-
const freeGB =
|
|
1178
|
+
const freeGB = getAvailableMemoryGB();
|
|
1158
1179
|
const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
|
|
1159
1180
|
if (totalGB <= 8) {
|
|
1160
1181
|
process.stderr.write(
|
|
@@ -1163,9 +1184,9 @@ function spawnDaemon() {
|
|
|
1163
1184
|
);
|
|
1164
1185
|
return;
|
|
1165
1186
|
}
|
|
1166
|
-
if (totalGB <= 16 && freeGB <
|
|
1187
|
+
if (totalGB <= 16 && freeGB < 2) {
|
|
1167
1188
|
process.stderr.write(
|
|
1168
|
-
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB
|
|
1189
|
+
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
|
|
1169
1190
|
`
|
|
1170
1191
|
);
|
|
1171
1192
|
return;
|
package/dist/index.js
CHANGED
|
@@ -1504,7 +1504,7 @@ async function ensureCompatibilityViews(prisma) {
|
|
|
1504
1504
|
for (const mapping of VIEW_MAPPINGS) {
|
|
1505
1505
|
const relation = mapping.source.replace(/"/g, "");
|
|
1506
1506
|
const rows = await prisma.$queryRawUnsafe(
|
|
1507
|
-
"SELECT to_regclass($1) AS regclass",
|
|
1507
|
+
"SELECT to_regclass($1)::text AS regclass",
|
|
1508
1508
|
relation
|
|
1509
1509
|
);
|
|
1510
1510
|
if (!rows[0]?.regclass) {
|
|
@@ -1858,8 +1858,29 @@ function findPackageRoot() {
|
|
|
1858
1858
|
}
|
|
1859
1859
|
return null;
|
|
1860
1860
|
}
|
|
1861
|
+
function getAvailableMemoryGB() {
|
|
1862
|
+
if (process.platform === "darwin") {
|
|
1863
|
+
try {
|
|
1864
|
+
const { execSync: execSync8 } = __require("child_process");
|
|
1865
|
+
const vmstat = execSync8("vm_stat", { encoding: "utf8" });
|
|
1866
|
+
const pageSize = 16384;
|
|
1867
|
+
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1868
|
+
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
1869
|
+
const free = vmstat.match(/Pages free:\s+(\d+)/);
|
|
1870
|
+
const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
|
|
1871
|
+
const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
|
|
1872
|
+
const freePages = free ? parseInt(free[1], 10) : 0;
|
|
1873
|
+
const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
|
|
1874
|
+
const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
|
|
1875
|
+
return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
|
|
1876
|
+
} catch {
|
|
1877
|
+
return os7.freemem() / (1024 * 1024 * 1024);
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
return os7.freemem() / (1024 * 1024 * 1024);
|
|
1881
|
+
}
|
|
1861
1882
|
function spawnDaemon() {
|
|
1862
|
-
const freeGB =
|
|
1883
|
+
const freeGB = getAvailableMemoryGB();
|
|
1863
1884
|
const totalGB = os7.totalmem() / (1024 * 1024 * 1024);
|
|
1864
1885
|
if (totalGB <= 8) {
|
|
1865
1886
|
process.stderr.write(
|
|
@@ -1868,9 +1889,9 @@ function spawnDaemon() {
|
|
|
1868
1889
|
);
|
|
1869
1890
|
return;
|
|
1870
1891
|
}
|
|
1871
|
-
if (totalGB <= 16 && freeGB <
|
|
1892
|
+
if (totalGB <= 16 && freeGB < 2) {
|
|
1872
1893
|
process.stderr.write(
|
|
1873
|
-
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB
|
|
1894
|
+
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
|
|
1874
1895
|
`
|
|
1875
1896
|
);
|
|
1876
1897
|
return;
|
|
@@ -14128,6 +14149,7 @@ var WhatsAppAdapter = class {
|
|
|
14128
14149
|
// src/gateway/adapters/signal.ts
|
|
14129
14150
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
14130
14151
|
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
14152
|
+
var POLL_INTERVAL_MS = 2e3;
|
|
14131
14153
|
var SignalAdapter = class {
|
|
14132
14154
|
platform = "signal";
|
|
14133
14155
|
baseUrl = "";
|
|
@@ -14135,12 +14157,13 @@ var SignalAdapter = class {
|
|
|
14135
14157
|
abortController = null;
|
|
14136
14158
|
messageHandler = null;
|
|
14137
14159
|
_connected = false;
|
|
14160
|
+
pollTimer = null;
|
|
14138
14161
|
normalizeBaseUrl(url) {
|
|
14139
14162
|
const trimmed = url.trim();
|
|
14140
14163
|
if (/^https?:\/\//i.test(trimmed)) {
|
|
14141
14164
|
return trimmed.replace(/\/+$/, "");
|
|
14142
14165
|
}
|
|
14143
|
-
return `
|
|
14166
|
+
return `http://${trimmed}`.replace(/\/+$/, "");
|
|
14144
14167
|
}
|
|
14145
14168
|
async connect(config2) {
|
|
14146
14169
|
this.baseUrl = this.normalizeBaseUrl(
|
|
@@ -14150,12 +14173,12 @@ var SignalAdapter = class {
|
|
|
14150
14173
|
const check = await this.healthCheck();
|
|
14151
14174
|
if (!check.connected) {
|
|
14152
14175
|
throw new Error(
|
|
14153
|
-
`signal-cli
|
|
14176
|
+
`signal-cli REST API not reachable at ${this.baseUrl}. Ensure bbernhard/signal-cli-rest-api container is running.`
|
|
14154
14177
|
);
|
|
14155
14178
|
}
|
|
14156
14179
|
this._connected = true;
|
|
14157
14180
|
this.abortController = new AbortController();
|
|
14158
|
-
void this.
|
|
14181
|
+
void this.startPolling();
|
|
14159
14182
|
void this.syncContacts().catch((err) => {
|
|
14160
14183
|
console.error("[signal] Contact sync failed:", err);
|
|
14161
14184
|
});
|
|
@@ -14166,6 +14189,10 @@ var SignalAdapter = class {
|
|
|
14166
14189
|
async disconnect() {
|
|
14167
14190
|
this.abortController?.abort();
|
|
14168
14191
|
this.abortController = null;
|
|
14192
|
+
if (this.pollTimer) {
|
|
14193
|
+
clearTimeout(this.pollTimer);
|
|
14194
|
+
this.pollTimer = null;
|
|
14195
|
+
}
|
|
14169
14196
|
this._connected = false;
|
|
14170
14197
|
}
|
|
14171
14198
|
onMessage(handler) {
|
|
@@ -14173,21 +14200,34 @@ var SignalAdapter = class {
|
|
|
14173
14200
|
}
|
|
14174
14201
|
async sendText(channelId, text, _options) {
|
|
14175
14202
|
const isGroup = channelId.startsWith("group:");
|
|
14176
|
-
const
|
|
14203
|
+
const body = {
|
|
14177
14204
|
message: text,
|
|
14178
|
-
|
|
14205
|
+
number: this.account,
|
|
14206
|
+
...isGroup ? { recipients: [], group_id: channelId.slice("group:".length) } : { recipients: [channelId] }
|
|
14179
14207
|
};
|
|
14180
|
-
|
|
14181
|
-
|
|
14208
|
+
const res = await fetch(`${this.baseUrl}/v2/send`, {
|
|
14209
|
+
method: "POST",
|
|
14210
|
+
headers: { "Content-Type": "application/json" },
|
|
14211
|
+
body: JSON.stringify(body),
|
|
14212
|
+
signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS)
|
|
14213
|
+
});
|
|
14214
|
+
if (!res.ok) {
|
|
14215
|
+
const errText = await res.text().catch(() => "");
|
|
14216
|
+
throw new Error(`Signal send failed (${res.status}): ${errText}`);
|
|
14182
14217
|
}
|
|
14183
|
-
await this.rpcRequest("send", params);
|
|
14184
14218
|
}
|
|
14185
14219
|
async sendTyping(channelId) {
|
|
14186
14220
|
try {
|
|
14187
14221
|
const isGroup = channelId.startsWith("group:");
|
|
14188
|
-
|
|
14189
|
-
|
|
14190
|
-
|
|
14222
|
+
const endpoint = isGroup ? `${this.baseUrl}/v1/typing-indicator/${this.account}` : `${this.baseUrl}/v1/typing-indicator/${this.account}`;
|
|
14223
|
+
await fetch(endpoint, {
|
|
14224
|
+
method: "PUT",
|
|
14225
|
+
headers: { "Content-Type": "application/json" },
|
|
14226
|
+
body: JSON.stringify({
|
|
14227
|
+
recipient: isGroup ? void 0 : channelId,
|
|
14228
|
+
group_id: isGroup ? channelId.slice("group:".length) : void 0
|
|
14229
|
+
}),
|
|
14230
|
+
signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS)
|
|
14191
14231
|
});
|
|
14192
14232
|
} catch {
|
|
14193
14233
|
}
|
|
@@ -14196,7 +14236,7 @@ var SignalAdapter = class {
|
|
|
14196
14236
|
if (!this.baseUrl) return { connected: this._connected };
|
|
14197
14237
|
const start = Date.now();
|
|
14198
14238
|
try {
|
|
14199
|
-
const res = await fetch(`${this.baseUrl}/
|
|
14239
|
+
const res = await fetch(`${this.baseUrl}/v1/about`, {
|
|
14200
14240
|
method: "GET",
|
|
14201
14241
|
signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS)
|
|
14202
14242
|
});
|
|
@@ -14210,96 +14250,48 @@ var SignalAdapter = class {
|
|
|
14210
14250
|
return { connected: false };
|
|
14211
14251
|
}
|
|
14212
14252
|
}
|
|
14213
|
-
async
|
|
14214
|
-
const id = randomUUID10();
|
|
14215
|
-
const res = await fetch(`${this.baseUrl}/api/v1/rpc`, {
|
|
14216
|
-
method: "POST",
|
|
14217
|
-
headers: { "Content-Type": "application/json" },
|
|
14218
|
-
body: JSON.stringify({ jsonrpc: "2.0", method, params, id }),
|
|
14219
|
-
signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS)
|
|
14220
|
-
});
|
|
14221
|
-
if (res.status === 201) return void 0;
|
|
14222
|
-
const text = await res.text();
|
|
14223
|
-
if (!text) throw new Error(`Signal RPC empty response (${res.status})`);
|
|
14224
|
-
const parsed = JSON.parse(text);
|
|
14225
|
-
if (parsed.error) {
|
|
14226
|
-
throw new Error(
|
|
14227
|
-
`Signal RPC ${parsed.error.code ?? "unknown"}: ${parsed.error.message ?? "error"}`
|
|
14228
|
-
);
|
|
14229
|
-
}
|
|
14230
|
-
return parsed.result;
|
|
14231
|
-
}
|
|
14232
|
-
async startEventStream() {
|
|
14233
|
-
const url = new URL(`${this.baseUrl}/api/v1/events`);
|
|
14234
|
-
if (this.account) {
|
|
14235
|
-
url.searchParams.set("account", this.account);
|
|
14236
|
-
}
|
|
14253
|
+
async startPolling() {
|
|
14237
14254
|
while (this.abortController && !this.abortController.signal.aborted) {
|
|
14238
14255
|
try {
|
|
14239
|
-
|
|
14240
|
-
method: "GET",
|
|
14241
|
-
headers: { Accept: "text/event-stream" },
|
|
14242
|
-
signal: this.abortController.signal
|
|
14243
|
-
});
|
|
14244
|
-
if (!res.ok || !res.body) {
|
|
14245
|
-
throw new Error(`Signal SSE failed (${res.status})`);
|
|
14246
|
-
}
|
|
14247
|
-
const reader = res.body.getReader();
|
|
14248
|
-
const decoder = new TextDecoder();
|
|
14249
|
-
let buffer = "";
|
|
14250
|
-
let currentEvent = {};
|
|
14251
|
-
const flushEvent = () => {
|
|
14252
|
-
if (currentEvent.data) {
|
|
14253
|
-
void this.handleSseEvent(currentEvent);
|
|
14254
|
-
}
|
|
14255
|
-
currentEvent = {};
|
|
14256
|
-
};
|
|
14257
|
-
while (true) {
|
|
14258
|
-
const { value, done } = await reader.read();
|
|
14259
|
-
if (done) break;
|
|
14260
|
-
buffer += decoder.decode(value, { stream: true });
|
|
14261
|
-
let lineEnd = buffer.indexOf("\n");
|
|
14262
|
-
while (lineEnd !== -1) {
|
|
14263
|
-
let line = buffer.slice(0, lineEnd);
|
|
14264
|
-
buffer = buffer.slice(lineEnd + 1);
|
|
14265
|
-
if (line.endsWith("\r")) line = line.slice(0, -1);
|
|
14266
|
-
if (line === "") {
|
|
14267
|
-
flushEvent();
|
|
14268
|
-
} else if (!line.startsWith(":")) {
|
|
14269
|
-
const colonIdx = line.indexOf(":");
|
|
14270
|
-
if (colonIdx !== -1) {
|
|
14271
|
-
const field = line.slice(0, colonIdx).trim();
|
|
14272
|
-
const val = line.slice(colonIdx + 1).replace(/^ /, "");
|
|
14273
|
-
if (field === "event") currentEvent.event = val;
|
|
14274
|
-
else if (field === "data") {
|
|
14275
|
-
currentEvent.data = currentEvent.data ? `${currentEvent.data}
|
|
14276
|
-
${val}` : val;
|
|
14277
|
-
}
|
|
14278
|
-
}
|
|
14279
|
-
}
|
|
14280
|
-
lineEnd = buffer.indexOf("\n");
|
|
14281
|
-
}
|
|
14282
|
-
}
|
|
14256
|
+
await this.pollMessages();
|
|
14283
14257
|
} catch (err) {
|
|
14284
14258
|
if (this.abortController?.signal.aborted) return;
|
|
14285
|
-
console.error("[signal]
|
|
14286
|
-
await new Promise((r) => setTimeout(r, 5e3));
|
|
14259
|
+
console.error("[signal] Poll error:", err);
|
|
14287
14260
|
}
|
|
14261
|
+
await new Promise((resolve) => {
|
|
14262
|
+
this.pollTimer = setTimeout(resolve, POLL_INTERVAL_MS);
|
|
14263
|
+
});
|
|
14288
14264
|
}
|
|
14289
14265
|
}
|
|
14290
|
-
async
|
|
14291
|
-
if (!
|
|
14292
|
-
|
|
14293
|
-
|
|
14294
|
-
|
|
14295
|
-
|
|
14296
|
-
|
|
14266
|
+
async pollMessages() {
|
|
14267
|
+
if (!this.account || !this.messageHandler) return;
|
|
14268
|
+
const res = await fetch(
|
|
14269
|
+
`${this.baseUrl}/v1/receive/${encodeURIComponent(this.account)}`,
|
|
14270
|
+
{
|
|
14271
|
+
method: "GET",
|
|
14272
|
+
signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS)
|
|
14273
|
+
}
|
|
14274
|
+
);
|
|
14275
|
+
if (!res.ok) {
|
|
14276
|
+
if (res.status === 400) {
|
|
14277
|
+
return;
|
|
14278
|
+
}
|
|
14279
|
+
throw new Error(`Signal receive failed (${res.status})`);
|
|
14280
|
+
}
|
|
14281
|
+
const entries = await res.json();
|
|
14282
|
+
if (!Array.isArray(entries) || entries.length === 0) return;
|
|
14283
|
+
for (const entry of entries) {
|
|
14284
|
+
await this.handleEntry(entry);
|
|
14297
14285
|
}
|
|
14298
|
-
|
|
14286
|
+
}
|
|
14287
|
+
async handleEntry(entry) {
|
|
14288
|
+
if (!this.messageHandler) return;
|
|
14289
|
+
const envelope = entry.envelope;
|
|
14299
14290
|
if (!envelope) return;
|
|
14300
|
-
const senderId = envelope.sourceNumber ?? envelope.sourceUuid ?? "";
|
|
14301
|
-
if (envelope.
|
|
14302
|
-
const rm = envelope.
|
|
14291
|
+
const senderId = envelope.sourceNumber ?? envelope.source ?? envelope.sourceUuid ?? "";
|
|
14292
|
+
if (envelope.dataMessage?.reaction) {
|
|
14293
|
+
const rm = envelope.dataMessage.reaction;
|
|
14294
|
+
if (rm.isRemove) return;
|
|
14303
14295
|
const normalized2 = {
|
|
14304
14296
|
messageId: randomUUID10(),
|
|
14305
14297
|
platform: "signal",
|
|
@@ -14311,11 +14303,11 @@ ${val}` : val;
|
|
|
14311
14303
|
timestamp: new Date(
|
|
14312
14304
|
envelope.timestamp ?? Date.now()
|
|
14313
14305
|
).toISOString(),
|
|
14314
|
-
raw:
|
|
14306
|
+
raw: entry,
|
|
14315
14307
|
dataCategory: "reaction",
|
|
14316
14308
|
reaction: {
|
|
14317
|
-
emoji: rm.emoji,
|
|
14318
|
-
targetMessageId: String(rm.
|
|
14309
|
+
emoji: rm.emoji ?? "",
|
|
14310
|
+
targetMessageId: String(rm.targetSentTimestamp ?? ""),
|
|
14319
14311
|
reactedBy: senderId,
|
|
14320
14312
|
timestamp: new Date(
|
|
14321
14313
|
envelope.timestamp ?? Date.now()
|
|
@@ -14327,7 +14319,7 @@ ${val}` : val;
|
|
|
14327
14319
|
}
|
|
14328
14320
|
if (envelope.receiptMessage) {
|
|
14329
14321
|
const rcpt = envelope.receiptMessage;
|
|
14330
|
-
for (const ts2 of rcpt.timestamps) {
|
|
14322
|
+
for (const ts2 of rcpt.timestamps ?? []) {
|
|
14331
14323
|
const normalized2 = {
|
|
14332
14324
|
messageId: randomUUID10(),
|
|
14333
14325
|
platform: "signal",
|
|
@@ -14339,11 +14331,11 @@ ${val}` : val;
|
|
|
14339
14331
|
timestamp: new Date(
|
|
14340
14332
|
envelope.timestamp ?? Date.now()
|
|
14341
14333
|
).toISOString(),
|
|
14342
|
-
raw:
|
|
14334
|
+
raw: entry,
|
|
14343
14335
|
dataCategory: "read_receipt",
|
|
14344
14336
|
readReceipt: {
|
|
14345
14337
|
messageId: String(ts2),
|
|
14346
|
-
status: rcpt.type === "
|
|
14338
|
+
status: rcpt.type === "READ" ? "read" : "delivered",
|
|
14347
14339
|
timestamp: new Date(
|
|
14348
14340
|
envelope.timestamp ?? Date.now()
|
|
14349
14341
|
).toISOString(),
|
|
@@ -14357,6 +14349,7 @@ ${val}` : val;
|
|
|
14357
14349
|
if (envelope.editMessage) {
|
|
14358
14350
|
const em = envelope.editMessage;
|
|
14359
14351
|
const dm2 = em.dataMessage;
|
|
14352
|
+
if (!dm2) return;
|
|
14360
14353
|
const isGroup2 = !!dm2.groupInfo?.groupId;
|
|
14361
14354
|
const normalized2 = {
|
|
14362
14355
|
messageId: String(dm2.timestamp ?? randomUUID10()),
|
|
@@ -14369,11 +14362,11 @@ ${val}` : val;
|
|
|
14369
14362
|
timestamp: new Date(
|
|
14370
14363
|
envelope.timestamp ?? Date.now()
|
|
14371
14364
|
).toISOString(),
|
|
14372
|
-
media: this.extractMedia(dm2),
|
|
14373
|
-
raw:
|
|
14365
|
+
media: this.extractMedia(dm2.attachments),
|
|
14366
|
+
raw: entry,
|
|
14374
14367
|
dataCategory: "edit",
|
|
14375
14368
|
replyTo: {
|
|
14376
|
-
messageId: String(em.
|
|
14369
|
+
messageId: String(em.targetSentTimestamp ?? ""),
|
|
14377
14370
|
text: "",
|
|
14378
14371
|
senderId
|
|
14379
14372
|
}
|
|
@@ -14395,13 +14388,13 @@ ${val}` : val;
|
|
|
14395
14388
|
timestamp: new Date(
|
|
14396
14389
|
envelope.timestamp ?? Date.now()
|
|
14397
14390
|
).toISOString(),
|
|
14398
|
-
media: this.extractMedia(dm),
|
|
14391
|
+
media: this.extractMedia(dm.attachments),
|
|
14399
14392
|
replyTo: dm.quote ? {
|
|
14400
14393
|
messageId: String(dm.quote.id ?? ""),
|
|
14401
14394
|
text: dm.quote.text ?? "",
|
|
14402
|
-
senderId: dm.quote.
|
|
14395
|
+
senderId: dm.quote.author ?? ""
|
|
14403
14396
|
} : void 0,
|
|
14404
|
-
raw:
|
|
14397
|
+
raw: entry,
|
|
14405
14398
|
dataCategory: "message"
|
|
14406
14399
|
};
|
|
14407
14400
|
await this.emitMessage(normalized);
|
|
@@ -14414,12 +14407,15 @@ ${val}` : val;
|
|
|
14414
14407
|
console.error("[signal] Message handler error:", err);
|
|
14415
14408
|
}
|
|
14416
14409
|
}
|
|
14417
|
-
/** Import all Signal contacts
|
|
14410
|
+
/** Import all Signal contacts */
|
|
14418
14411
|
async syncContacts() {
|
|
14419
|
-
if (!this.messageHandler) return;
|
|
14420
|
-
const
|
|
14421
|
-
|
|
14422
|
-
|
|
14412
|
+
if (!this.messageHandler || !this.account) return;
|
|
14413
|
+
const res = await fetch(
|
|
14414
|
+
`${this.baseUrl}/v1/contacts/${encodeURIComponent(this.account)}`,
|
|
14415
|
+
{ signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS) }
|
|
14416
|
+
);
|
|
14417
|
+
if (!res.ok) return;
|
|
14418
|
+
const contacts = await res.json();
|
|
14423
14419
|
if (!Array.isArray(contacts)) return;
|
|
14424
14420
|
for (const contact of contacts) {
|
|
14425
14421
|
const phone = contact.number ?? "";
|
|
@@ -14446,12 +14442,15 @@ ${val}` : val;
|
|
|
14446
14442
|
}
|
|
14447
14443
|
console.log(`[signal] Synced ${contacts.length} contacts`);
|
|
14448
14444
|
}
|
|
14449
|
-
/** Import all Signal groups
|
|
14445
|
+
/** Import all Signal groups */
|
|
14450
14446
|
async syncGroups() {
|
|
14451
|
-
if (!this.messageHandler) return;
|
|
14452
|
-
const
|
|
14453
|
-
|
|
14454
|
-
|
|
14447
|
+
if (!this.messageHandler || !this.account) return;
|
|
14448
|
+
const res = await fetch(
|
|
14449
|
+
`${this.baseUrl}/v1/groups/${encodeURIComponent(this.account)}`,
|
|
14450
|
+
{ signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS) }
|
|
14451
|
+
);
|
|
14452
|
+
if (!res.ok) return;
|
|
14453
|
+
const groups = await res.json();
|
|
14455
14454
|
if (!Array.isArray(groups)) return;
|
|
14456
14455
|
for (const group of groups) {
|
|
14457
14456
|
const normalized = {
|
|
@@ -14476,15 +14475,19 @@ ${val}` : val;
|
|
|
14476
14475
|
}
|
|
14477
14476
|
console.log(`[signal] Synced ${groups.length} groups`);
|
|
14478
14477
|
}
|
|
14479
|
-
extractMedia(
|
|
14480
|
-
if (!
|
|
14481
|
-
return
|
|
14478
|
+
extractMedia(attachments) {
|
|
14479
|
+
if (!attachments?.length) return void 0;
|
|
14480
|
+
return attachments.map((att) => {
|
|
14482
14481
|
const ct = att.contentType ?? "";
|
|
14483
14482
|
let type = "document";
|
|
14484
14483
|
if (ct.startsWith("image/")) type = "image";
|
|
14485
14484
|
else if (ct.startsWith("video/")) type = "video";
|
|
14486
14485
|
else if (ct.startsWith("audio/")) type = "audio";
|
|
14487
|
-
return {
|
|
14486
|
+
return {
|
|
14487
|
+
type,
|
|
14488
|
+
fileName: att.filename ?? void 0,
|
|
14489
|
+
url: att.id ? `${this.baseUrl}/v1/attachments/${att.id}` : void 0
|
|
14490
|
+
};
|
|
14488
14491
|
});
|
|
14489
14492
|
}
|
|
14490
14493
|
};
|
|
@@ -15053,7 +15056,7 @@ import { promisify } from "util";
|
|
|
15053
15056
|
import os13 from "os";
|
|
15054
15057
|
import path21 from "path";
|
|
15055
15058
|
var execFileAsync = promisify(execFile);
|
|
15056
|
-
var
|
|
15059
|
+
var POLL_INTERVAL_MS2 = 5e3;
|
|
15057
15060
|
var MESSAGES_DB_PATH = path21.join(
|
|
15058
15061
|
process.env.HOME ?? os13.homedir(),
|
|
15059
15062
|
"Library/Messages/chat.db"
|
|
@@ -15090,7 +15093,7 @@ var IMessageAdapter = class {
|
|
|
15090
15093
|
console.log("[imessage] Connected via AppleScript bridge");
|
|
15091
15094
|
this.pollTimer = setInterval(() => {
|
|
15092
15095
|
void this.pollMessages();
|
|
15093
|
-
},
|
|
15096
|
+
}, POLL_INTERVAL_MS2);
|
|
15094
15097
|
}
|
|
15095
15098
|
async disconnect() {
|
|
15096
15099
|
if (this.pollTimer) {
|
package/dist/lib/cloud-sync.js
CHANGED
|
@@ -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
|
};
|
|
@@ -605,7 +611,7 @@ async function ensureCompatibilityViews(prisma) {
|
|
|
605
611
|
for (const mapping of VIEW_MAPPINGS) {
|
|
606
612
|
const relation = mapping.source.replace(/"/g, "");
|
|
607
613
|
const rows = await prisma.$queryRawUnsafe(
|
|
608
|
-
"SELECT to_regclass($1) AS regclass",
|
|
614
|
+
"SELECT to_regclass($1)::text AS regclass",
|
|
609
615
|
relation
|
|
610
616
|
);
|
|
611
617
|
if (!rows[0]?.regclass) {
|
|
@@ -959,8 +965,29 @@ function findPackageRoot() {
|
|
|
959
965
|
}
|
|
960
966
|
return null;
|
|
961
967
|
}
|
|
968
|
+
function getAvailableMemoryGB() {
|
|
969
|
+
if (process.platform === "darwin") {
|
|
970
|
+
try {
|
|
971
|
+
const { execSync: execSync2 } = __require("child_process");
|
|
972
|
+
const vmstat = execSync2("vm_stat", { encoding: "utf8" });
|
|
973
|
+
const pageSize = 16384;
|
|
974
|
+
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
975
|
+
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
976
|
+
const free = vmstat.match(/Pages free:\s+(\d+)/);
|
|
977
|
+
const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
|
|
978
|
+
const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
|
|
979
|
+
const freePages = free ? parseInt(free[1], 10) : 0;
|
|
980
|
+
const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
|
|
981
|
+
const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
|
|
982
|
+
return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
|
|
983
|
+
} catch {
|
|
984
|
+
return os4.freemem() / (1024 * 1024 * 1024);
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
return os4.freemem() / (1024 * 1024 * 1024);
|
|
988
|
+
}
|
|
962
989
|
function spawnDaemon() {
|
|
963
|
-
const freeGB =
|
|
990
|
+
const freeGB = getAvailableMemoryGB();
|
|
964
991
|
const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
|
|
965
992
|
if (totalGB <= 8) {
|
|
966
993
|
process.stderr.write(
|
|
@@ -969,9 +996,9 @@ function spawnDaemon() {
|
|
|
969
996
|
);
|
|
970
997
|
return;
|
|
971
998
|
}
|
|
972
|
-
if (totalGB <= 16 && freeGB <
|
|
999
|
+
if (totalGB <= 16 && freeGB < 2) {
|
|
973
1000
|
process.stderr.write(
|
|
974
|
-
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB
|
|
1001
|
+
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
|
|
975
1002
|
`
|
|
976
1003
|
);
|
|
977
1004
|
return;
|