@askexenow/exe-os 0.9.262 → 0.9.264
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/deploy/stack-manifests/v0.9.json +1 -1
- package/dist/bin/exe-doctor.js +1 -1
- package/dist/bin/exe-forget.js +1 -1
- package/dist/bin/exe-search.js +1 -1
- package/dist/bin/exe-support.js +1 -1
- package/dist/bin/registry-proxy.js +1 -1
- package/dist/{catchup-brief-QYHXH7X4.js → catchup-brief-VNX2SJ2B.js} +1 -1
- package/dist/{chunk-BJYXHSFN.js → chunk-3X555IGG.js} +1 -1
- package/dist/{chunk-SHN5O73O.js → chunk-FJUQ5L5R.js} +1 -1
- package/dist/{chunk-235ZCOYB.js → chunk-IBGC6JFX.js} +2 -2
- package/dist/{chunk-K6FHWGFL.js → chunk-Y32AMMDY.js} +3 -3
- package/dist/{chunk-RGKPO6UP.js → chunk-YGOUKUNX.js} +11 -6
- package/dist/hooks/error-recall.js +1 -1
- package/dist/hooks/manifest.json +4 -4
- package/dist/hooks/prompt-submit.js +2 -2
- package/dist/hooks/session-start.js +2 -2
- package/dist/lib/exe-daemon.js +2 -2
- package/dist/lib/hybrid-search.js +1 -1
- package/dist/lib/registry-proxy.js +1 -1
- package/dist/mcp/register-tools.js +5 -5
- package/dist/mcp/server.js +5 -5
- package/dist/{projection-worker-ONHS43GB.js → projection-worker-ZAUKM5Z3.js} +14 -6
- package/dist/{reranker-RPPWEE73.js → reranker-OZR43HRG.js} +1 -1
- package/dist/{support-outbox-SZVLHHZG.js → support-outbox-SO73Q5H2.js} +202 -7
- package/package.json +1 -1
- package/release-notes.json +26 -26
- /package/dist/{chunk-JBPOZ6LG.js → chunk-QCURGNWR.js} +0 -0
|
@@ -1180,7 +1180,7 @@
|
|
|
1180
1180
|
"healthUrl": "http://127.0.0.1:8765/health"
|
|
1181
1181
|
},
|
|
1182
1182
|
"gateway": {
|
|
1183
|
-
"image": "update.askexe.com/askexe/exe-gateway:v0.9.
|
|
1183
|
+
"image": "update.askexe.com/askexe/exe-gateway:v0.9.17",
|
|
1184
1184
|
"env": "GATEWAY_IMAGE_TAG",
|
|
1185
1185
|
"composeService": "exe-gateway",
|
|
1186
1186
|
"healthUrl": "http://127.0.0.1:3100/health"
|
package/dist/bin/exe-doctor.js
CHANGED
package/dist/bin/exe-forget.js
CHANGED
package/dist/bin/exe-search.js
CHANGED
package/dist/bin/exe-support.js
CHANGED
|
@@ -622,7 +622,7 @@ async function auditKeyHealth() {
|
|
|
622
622
|
}
|
|
623
623
|
async function auditOutbox() {
|
|
624
624
|
try {
|
|
625
|
-
const { getOutboxStatus } = await import("./support-outbox-
|
|
625
|
+
const { getOutboxStatus } = await import("./support-outbox-SO73Q5H2.js");
|
|
626
626
|
return await getOutboxStatus();
|
|
627
627
|
} catch {
|
|
628
628
|
return {
|
|
@@ -15,7 +15,7 @@ function registryProxyOptionsFromEnv(env = process.env) {
|
|
|
15
15
|
upstreamToken,
|
|
16
16
|
pullTokens,
|
|
17
17
|
allowedNamespace: env.EXE_REGISTRY_PROXY_ALLOWED_NAMESPACE || "askexe",
|
|
18
|
-
licenseValidatorUrl: env.EXE_REGISTRY_PROXY_LICENSE_VALIDATOR_URL || ""
|
|
18
|
+
licenseValidatorUrl: env.EXE_REGISTRY_PROXY_LICENSE_VALIDATOR_URL || "https://api.askexe.com/v1/license/validate"
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
21
|
function assertRegistryProxyConfig(options) {
|
|
@@ -275,7 +275,7 @@ function nextForPostFailure(status) {
|
|
|
275
275
|
return "Run `exe-os support health`; if it passes, send this output to AskExe.";
|
|
276
276
|
}
|
|
277
277
|
async function runFlush(json) {
|
|
278
|
-
const { flushSupportOutbox } = await import("./support-outbox-
|
|
278
|
+
const { flushSupportOutbox } = await import("./support-outbox-SO73Q5H2.js");
|
|
279
279
|
const result = await flushSupportOutbox({ maxPerFlush: 10 });
|
|
280
280
|
if (json) {
|
|
281
281
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -298,7 +298,7 @@ async function runFlush(json) {
|
|
|
298
298
|
console.log("");
|
|
299
299
|
}
|
|
300
300
|
async function runStatus(json) {
|
|
301
|
-
const { getOutboxStatus } = await import("./support-outbox-
|
|
301
|
+
const { getOutboxStatus } = await import("./support-outbox-SO73Q5H2.js");
|
|
302
302
|
const status = await getOutboxStatus();
|
|
303
303
|
if (json) {
|
|
304
304
|
console.log(JSON.stringify(status, null, 2));
|
|
@@ -288,7 +288,7 @@ async function hybridSearch(queryText, agentId, options) {
|
|
|
288
288
|
let rerankerAvailable = false;
|
|
289
289
|
if (process.env.EXE_IS_DAEMON === "1") {
|
|
290
290
|
try {
|
|
291
|
-
const { isRerankerAvailable } = await import("./reranker-
|
|
291
|
+
const { isRerankerAvailable } = await import("./reranker-OZR43HRG.js");
|
|
292
292
|
rerankerAvailable = isRerankerAvailable();
|
|
293
293
|
} catch {
|
|
294
294
|
}
|
|
@@ -452,7 +452,7 @@ async function hybridSearch(queryText, agentId, options) {
|
|
|
452
452
|
try {
|
|
453
453
|
let rerankedRecords;
|
|
454
454
|
if (graphContextMap.size > 0) {
|
|
455
|
-
const { rerankWithContext } = await import("./reranker-
|
|
455
|
+
const { rerankWithContext } = await import("./reranker-OZR43HRG.js");
|
|
456
456
|
const candidates = merged.map((m) => ({
|
|
457
457
|
text: m.raw_text,
|
|
458
458
|
context: graphContextMap.get(m.id)
|
|
@@ -460,7 +460,7 @@ async function hybridSearch(queryText, agentId, options) {
|
|
|
460
460
|
const scored = await rerankWithContext(effectiveQuery, candidates, rerankReturnLimit);
|
|
461
461
|
rerankedRecords = scored.map((s) => merged[s.index]);
|
|
462
462
|
} else {
|
|
463
|
-
const { rerank } = await import("./reranker-
|
|
463
|
+
const { rerank } = await import("./reranker-OZR43HRG.js");
|
|
464
464
|
rerankedRecords = await rerank(effectiveQuery, merged, rerankReturnLimit);
|
|
465
465
|
}
|
|
466
466
|
if (rerankedRecords.length > 0) {
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
isRerankerAvailable,
|
|
12
12
|
rerankWithScores
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-QCURGNWR.js";
|
|
14
14
|
import {
|
|
15
15
|
getCachedLicenseGate
|
|
16
16
|
} from "./chunk-2WBBVEIB.js";
|
|
@@ -121,7 +121,7 @@ import {
|
|
|
121
121
|
fixShards,
|
|
122
122
|
formatReport,
|
|
123
123
|
runAudit
|
|
124
|
-
} from "./chunk-
|
|
124
|
+
} from "./chunk-3X555IGG.js";
|
|
125
125
|
import {
|
|
126
126
|
runHealthCheck
|
|
127
127
|
} from "./chunk-RQI5TG5F.js";
|
|
@@ -129,7 +129,7 @@ import {
|
|
|
129
129
|
hasFailures,
|
|
130
130
|
runHealth,
|
|
131
131
|
runTest
|
|
132
|
-
} from "./chunk-
|
|
132
|
+
} from "./chunk-IBGC6JFX.js";
|
|
133
133
|
import {
|
|
134
134
|
supportAdminHeaders
|
|
135
135
|
} from "./chunk-2XZ6X3PJ.js";
|
|
@@ -194,7 +194,7 @@ import {
|
|
|
194
194
|
import {
|
|
195
195
|
hybridSearch,
|
|
196
196
|
recentRecords
|
|
197
|
-
} from "./chunk-
|
|
197
|
+
} from "./chunk-Y32AMMDY.js";
|
|
198
198
|
import {
|
|
199
199
|
attachDocumentMetadata,
|
|
200
200
|
flushBatch,
|
|
@@ -11847,13 +11847,18 @@ function findPackageRoot() {
|
|
|
11847
11847
|
throw new Error("Cannot find package root");
|
|
11848
11848
|
}
|
|
11849
11849
|
var execFileAsync2 = promisify2(execFile2);
|
|
11850
|
+
function childCliEnv() {
|
|
11851
|
+
const env = { ...process.env };
|
|
11852
|
+
delete env.EXE_IS_DAEMON;
|
|
11853
|
+
return env;
|
|
11854
|
+
}
|
|
11850
11855
|
async function runCommand(command, args, timeout = 6e4) {
|
|
11851
11856
|
const printable = [command, ...args].join(" ");
|
|
11852
11857
|
try {
|
|
11853
11858
|
const { stdout, stderr } = await execFileAsync2(command, args, {
|
|
11854
11859
|
timeout,
|
|
11855
11860
|
maxBuffer: 1024 * 1024,
|
|
11856
|
-
env:
|
|
11861
|
+
env: childCliEnv()
|
|
11857
11862
|
});
|
|
11858
11863
|
return { ok: true, command: printable, text: `${stdout}${stderr ? `
|
|
11859
11864
|
${stderr}` : ""}`.trim() || "OK" };
|
|
@@ -11879,7 +11884,7 @@ async function runDistScript(scriptName, args, timeout = 6e4) {
|
|
|
11879
11884
|
const { stdout, stderr } = await execFileAsync2(process.execPath, [scriptPath, ...args], {
|
|
11880
11885
|
timeout,
|
|
11881
11886
|
maxBuffer: 1024 * 1024,
|
|
11882
|
-
env:
|
|
11887
|
+
env: childCliEnv()
|
|
11883
11888
|
});
|
|
11884
11889
|
return { ok: true, command: printable, text: `${stdout}${stderr ? `
|
|
11885
11890
|
${stderr}` : ""}`.trim() || "OK" };
|
package/dist/hooks/manifest.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
|
-
"generatedAt": "2026-06-
|
|
3
|
+
"generatedAt": "2026-06-10T03:14:04.639Z",
|
|
4
4
|
"hashes": {
|
|
5
5
|
"bug-report-worker.js": "5b5c47ed54222e7e9e9099dbe0032076b549d406fd0fad91e4685d345f4d465f",
|
|
6
6
|
"codex-stop-task-finalizer.js": "4470796421e93af8416e83e6822e14acfa72ecc96da6574fbfb38965f2e7d7e6",
|
|
7
7
|
"commit-complete.js": "d6a053e16241909b3ded37c13fa2868bf93f0fe593b5dcc2d7117fd367744861",
|
|
8
|
-
"error-recall.js": "
|
|
8
|
+
"error-recall.js": "3e1bb5b447fe8a7fe935e530a4534db1d455f36f361aac677da47ad413e5c2ce",
|
|
9
9
|
"exe-heartbeat-hook.js": "351dd0a9c4c1f21bf7faa3a5431b0f71f6f55bc629a6503394e1e696a9589b08",
|
|
10
10
|
"ingest-worker.js": "1f6a591f863d5bc540b0e11bb382d3ba13cf761709e4a82313f6f1d9fb9c18e2",
|
|
11
11
|
"ingest.js": "f040375367df68749331bbf3ea5527b754840f0ed2db621c966abe51b6375890",
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
"post-tool-combined.js": "3fbbb2d941e264291567a6da97bb02523c907a0edf742ef6d59b13e5956cd4f8",
|
|
16
16
|
"pre-compact.js": "8e7512e75a0407a5c632ebfb5f23595507c5d8972afcae839462f719ea56a973",
|
|
17
17
|
"pre-tool-use.js": "f50d7d8b341109bf5f927295d9227877b691989fdf3ef04565e7579dfac8a66a",
|
|
18
|
-
"prompt-submit.js": "
|
|
18
|
+
"prompt-submit.js": "aa73cc8af3985beb3ee81142f3948db758b69420248f135e4c71ba29e7ce901d",
|
|
19
19
|
"session-end.js": "b88b3007dadaa427f748154551790648742627ac788a8fa8f76761ad8b45ef90",
|
|
20
|
-
"session-start.js": "
|
|
20
|
+
"session-start.js": "87238eebedce4b93d2b4836651de5341c44e46b3ab34f81982feb09f761ce610",
|
|
21
21
|
"stop.js": "ab962df8d9b91f04e3eb3708e67300fb0f64cd57c25d814312bc84485c4d00ae",
|
|
22
22
|
"subagent-stop.js": "626924150de92ca5e509066b016950d6ce62d4df5e58a0d0713a4d36705aaefc",
|
|
23
23
|
"summary-worker.js": "dc0ac0448fbec252aacccf8b8a2dfe2e296ee0306e5ce41b1362db2318307b66"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
hybridSearch,
|
|
3
3
|
lightweightSearch
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-Y32AMMDY.js";
|
|
5
5
|
import {
|
|
6
6
|
initStore
|
|
7
7
|
} from "../chunk-6YHVX54O.js";
|
|
@@ -673,7 +673,7 @@ ${typedSummaries.join("\n---\n")}`;
|
|
|
673
673
|
process.stderr.write("[prompt-submit] hook main handler: " + (e instanceof Error ? e.message : String(e)) + "\n");
|
|
674
674
|
}
|
|
675
675
|
try {
|
|
676
|
-
const { flushSupportOutbox } = await import("../support-outbox-
|
|
676
|
+
const { flushSupportOutbox } = await import("../support-outbox-SO73Q5H2.js");
|
|
677
677
|
void flushSupportOutbox();
|
|
678
678
|
} catch {
|
|
679
679
|
}
|
|
@@ -163,7 +163,7 @@ You are **${ag.agentId}**. Daemon is degraded \u2014 memory unavailable.
|
|
|
163
163
|
query = `last actions on ${projectName}`;
|
|
164
164
|
header = "## Resuming Session\nHere's where you left off:";
|
|
165
165
|
try {
|
|
166
|
-
const { buildCatchupBrief } = await import("../catchup-brief-
|
|
166
|
+
const { buildCatchupBrief } = await import("../catchup-brief-VNX2SJ2B.js");
|
|
167
167
|
const brief = await buildCatchupBrief(
|
|
168
168
|
agentId,
|
|
169
169
|
projectName,
|
|
@@ -376,7 +376,7 @@ This token is checked against browser-scraped content. If a page contains it, th
|
|
|
376
376
|
} catch {
|
|
377
377
|
}
|
|
378
378
|
try {
|
|
379
|
-
const { flushSupportOutbox } = await import("../support-outbox-
|
|
379
|
+
const { flushSupportOutbox } = await import("../support-outbox-SO73Q5H2.js");
|
|
380
380
|
void flushSupportOutbox();
|
|
381
381
|
} catch {
|
|
382
382
|
}
|
package/dist/lib/exe-daemon.js
CHANGED
|
@@ -1230,7 +1230,7 @@ async function shutdown() {
|
|
|
1230
1230
|
`);
|
|
1231
1231
|
}
|
|
1232
1232
|
try {
|
|
1233
|
-
const { stopProjectionWorker } = await import("../projection-worker-
|
|
1233
|
+
const { stopProjectionWorker } = await import("../projection-worker-ZAUKM5Z3.js");
|
|
1234
1234
|
stopProjectionWorker();
|
|
1235
1235
|
} catch {
|
|
1236
1236
|
}
|
|
@@ -4996,7 +4996,7 @@ try {
|
|
|
4996
4996
|
process.stderr.write("[exed] Tool telemetry started (flush every 5m)\n");
|
|
4997
4997
|
setTimeout(async () => {
|
|
4998
4998
|
try {
|
|
4999
|
-
const { startProjectionWorker } = await import("../projection-worker-
|
|
4999
|
+
const { startProjectionWorker } = await import("../projection-worker-ZAUKM5Z3.js");
|
|
5000
5000
|
startProjectionWorker();
|
|
5001
5001
|
} catch {
|
|
5002
5002
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
registerAllTools
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-YGOUKUNX.js";
|
|
4
4
|
import "../chunk-O4D4DSNZ.js";
|
|
5
5
|
import "../chunk-557C2IGL.js";
|
|
6
6
|
import "../chunk-KPVRGCOC.js";
|
|
7
7
|
import "../chunk-PK7H6FFK.js";
|
|
8
|
-
import "../chunk-
|
|
8
|
+
import "../chunk-QCURGNWR.js";
|
|
9
9
|
import "../chunk-2WBBVEIB.js";
|
|
10
10
|
import "../chunk-AU64ZSNH.js";
|
|
11
11
|
import "../chunk-BBPRL2MP.js";
|
|
@@ -38,9 +38,9 @@ import "../chunk-L5RL4GH4.js";
|
|
|
38
38
|
import "../chunk-GP6G6EQI.js";
|
|
39
39
|
import "../chunk-GUMRIUI5.js";
|
|
40
40
|
import "../chunk-I7AW4237.js";
|
|
41
|
-
import "../chunk-
|
|
41
|
+
import "../chunk-3X555IGG.js";
|
|
42
42
|
import "../chunk-RQI5TG5F.js";
|
|
43
|
-
import "../chunk-
|
|
43
|
+
import "../chunk-IBGC6JFX.js";
|
|
44
44
|
import "../chunk-2XZ6X3PJ.js";
|
|
45
45
|
import "../chunk-MMRUBN3I.js";
|
|
46
46
|
import "../chunk-2WH32VJI.js";
|
|
@@ -61,7 +61,7 @@ import "../chunk-GMUZHA5J.js";
|
|
|
61
61
|
import "../chunk-45W7EDXB.js";
|
|
62
62
|
import "../chunk-Z2AEOVEZ.js";
|
|
63
63
|
import "../chunk-7IZWLMTP.js";
|
|
64
|
-
import "../chunk-
|
|
64
|
+
import "../chunk-Y32AMMDY.js";
|
|
65
65
|
import "../chunk-6YHVX54O.js";
|
|
66
66
|
import "../chunk-CHCA3ZM2.js";
|
|
67
67
|
import "../chunk-P2XNRKEL.js";
|
package/dist/mcp/server.js
CHANGED
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
} from "../chunk-V4TZI6EO.js";
|
|
4
4
|
import {
|
|
5
5
|
registerAllTools
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-YGOUKUNX.js";
|
|
7
7
|
import "../chunk-O4D4DSNZ.js";
|
|
8
8
|
import "../chunk-557C2IGL.js";
|
|
9
9
|
import "../chunk-KPVRGCOC.js";
|
|
10
10
|
import "../chunk-PK7H6FFK.js";
|
|
11
|
-
import "../chunk-
|
|
11
|
+
import "../chunk-QCURGNWR.js";
|
|
12
12
|
import {
|
|
13
13
|
initLicenseGate
|
|
14
14
|
} from "../chunk-2WBBVEIB.js";
|
|
@@ -46,9 +46,9 @@ import "../chunk-L5RL4GH4.js";
|
|
|
46
46
|
import "../chunk-GP6G6EQI.js";
|
|
47
47
|
import "../chunk-GUMRIUI5.js";
|
|
48
48
|
import "../chunk-I7AW4237.js";
|
|
49
|
-
import "../chunk-
|
|
49
|
+
import "../chunk-3X555IGG.js";
|
|
50
50
|
import "../chunk-RQI5TG5F.js";
|
|
51
|
-
import "../chunk-
|
|
51
|
+
import "../chunk-IBGC6JFX.js";
|
|
52
52
|
import "../chunk-2XZ6X3PJ.js";
|
|
53
53
|
import "../chunk-MMRUBN3I.js";
|
|
54
54
|
import "../chunk-2WH32VJI.js";
|
|
@@ -71,7 +71,7 @@ import "../chunk-GMUZHA5J.js";
|
|
|
71
71
|
import "../chunk-45W7EDXB.js";
|
|
72
72
|
import "../chunk-Z2AEOVEZ.js";
|
|
73
73
|
import "../chunk-7IZWLMTP.js";
|
|
74
|
-
import "../chunk-
|
|
74
|
+
import "../chunk-Y32AMMDY.js";
|
|
75
75
|
import {
|
|
76
76
|
disposeStore,
|
|
77
77
|
initStore
|
|
@@ -656,19 +656,27 @@ var projectionHandlers = {
|
|
|
656
656
|
targets.push("graph");
|
|
657
657
|
await ensureFilteredSchema(prisma);
|
|
658
658
|
const senderName = payload.sender_name ?? payload.contact_name ?? null;
|
|
659
|
-
const
|
|
659
|
+
const rawSender = payload.from ?? payload.phone ?? null;
|
|
660
660
|
const threadId = payload.conversation_id ?? payload.chat_id ?? event.source_id;
|
|
661
|
-
if (
|
|
661
|
+
if (rawSender) {
|
|
662
|
+
const bareSender = rawSender.replace(/@.*$/, "");
|
|
663
|
+
const phone = !rawSender.endsWith("@lid") && /^\+?\d{6,20}$/.test(bareSender) ? bareSender : null;
|
|
664
|
+
const name = senderName ?? phone ?? "Unknown (WhatsApp)";
|
|
662
665
|
const contactResult = await prisma.$queryRawUnsafe(
|
|
663
666
|
`INSERT INTO "filtered"."contacts" ("name", "phone", "platform", "platform_id", "last_seen")
|
|
664
667
|
VALUES ($1, $2, 'whatsapp', $3, $4)
|
|
665
668
|
ON CONFLICT ("platform", "platform_id") DO UPDATE SET
|
|
666
|
-
"name" =
|
|
669
|
+
"name" = CASE
|
|
670
|
+
WHEN EXCLUDED."name" IS NOT NULL AND EXCLUDED."name" <> 'Unknown (WhatsApp)' THEN EXCLUDED."name"
|
|
671
|
+
WHEN "filtered"."contacts"."name" ~ '@(lid|s\\.whatsapp\\.net)$' THEN EXCLUDED."name"
|
|
672
|
+
ELSE "filtered"."contacts"."name"
|
|
673
|
+
END,
|
|
674
|
+
"phone" = COALESCE(EXCLUDED."phone", "filtered"."contacts"."phone"),
|
|
667
675
|
"last_seen" = GREATEST("filtered"."contacts"."last_seen", EXCLUDED."last_seen")
|
|
668
676
|
RETURNING "id"`,
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
677
|
+
name,
|
|
678
|
+
phone,
|
|
679
|
+
rawSender,
|
|
672
680
|
event.timestamp
|
|
673
681
|
);
|
|
674
682
|
const contactId = contactResult[0]?.id;
|
|
@@ -5,16 +5,19 @@ import {
|
|
|
5
5
|
import "./chunk-MLKGABMK.js";
|
|
6
6
|
|
|
7
7
|
// src/lib/support-outbox.ts
|
|
8
|
-
import { readdirSync, readFileSync, writeFileSync, existsSync } from "fs";
|
|
8
|
+
import { mkdirSync, readdirSync, readFileSync, writeFileSync, existsSync } from "fs";
|
|
9
9
|
import path from "path";
|
|
10
10
|
import os from "os";
|
|
11
11
|
var EXE_DIR = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path.join(os.homedir(), ".exe-os");
|
|
12
12
|
var BUG_DIR = path.join(EXE_DIR, "bug-reports");
|
|
13
13
|
var FEATURE_DIR = path.join(EXE_DIR, "feature-requests");
|
|
14
|
+
var STATUS_UPDATE_DIR = path.join(EXE_DIR, "support-status-updates");
|
|
14
15
|
var SKIPPED_MARKER = "upstream_skipped: ttl_expired";
|
|
15
16
|
var TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
16
17
|
var BUG_ENDPOINT = "https://api.askexe.com/v1/support/bug-reports";
|
|
17
18
|
var FEATURE_ENDPOINT = "https://api.askexe.com/v1/support/feature-requests";
|
|
19
|
+
var CUSTOMER_STATUS_BASE_ENDPOINT = "https://api.askexe.com/v1/support";
|
|
20
|
+
var ADMIN_STATUS_BASE_ENDPOINT = "https://api.askexe.com/admin/support";
|
|
18
21
|
var DEFAULT_MAX_PER_FLUSH = 3;
|
|
19
22
|
var consecutiveFailures = 0;
|
|
20
23
|
var lastFailureTime = 0;
|
|
@@ -47,6 +50,35 @@ function loadSupportAdminToken() {
|
|
|
47
50
|
const support = config?.support;
|
|
48
51
|
return process.env.ASKEXE_SUPPORT_ADMIN_TOKEN || process.env.EXE_SUPPORT_ADMIN_TOKEN || support?.adminToken || support?.admin_token;
|
|
49
52
|
}
|
|
53
|
+
function normalizeBaseEndpoint(value, fallback) {
|
|
54
|
+
let raw = value || fallback;
|
|
55
|
+
try {
|
|
56
|
+
const parsed = new URL(raw);
|
|
57
|
+
if (parsed.hostname === "askexe.com" || parsed.hostname === "cloud.askexe.com") {
|
|
58
|
+
parsed.hostname = "api.askexe.com";
|
|
59
|
+
raw = parsed.toString();
|
|
60
|
+
}
|
|
61
|
+
} catch {
|
|
62
|
+
}
|
|
63
|
+
return raw.replace(/\/+$/, "").replace(/\/(bug-reports|feature-requests)\/?$/, "");
|
|
64
|
+
}
|
|
65
|
+
function buildStatusUpdateEndpoint(endpointPath, adminToken) {
|
|
66
|
+
const config = loadConfigFile();
|
|
67
|
+
const support = config?.support;
|
|
68
|
+
const routerUrl = process.env.API_ROUTER_URL?.replace(/\/+$/, "");
|
|
69
|
+
if (adminToken) {
|
|
70
|
+
const adminBase = normalizeBaseEndpoint(
|
|
71
|
+
process.env.ASKEXE_SUPPORT_ADMIN_ENDPOINT || support?.adminEndpoint || support?.admin_endpoint || ADMIN_STATUS_BASE_ENDPOINT,
|
|
72
|
+
ADMIN_STATUS_BASE_ENDPOINT
|
|
73
|
+
);
|
|
74
|
+
return `${adminBase}/${endpointPath.replace(/^\/+/, "")}`;
|
|
75
|
+
}
|
|
76
|
+
const customerBase = normalizeBaseEndpoint(
|
|
77
|
+
support?.bugReportEndpoint || process.env.EXE_BUG_REPORT_ENDPOINT || (routerUrl ? `${routerUrl}/v1/support` : CUSTOMER_STATUS_BASE_ENDPOINT),
|
|
78
|
+
CUSTOMER_STATUS_BASE_ENDPOINT
|
|
79
|
+
);
|
|
80
|
+
return `${customerBase}/${endpointPath.replace(/^\/+/, "")}`;
|
|
81
|
+
}
|
|
50
82
|
function readTrimmed(filePath) {
|
|
51
83
|
try {
|
|
52
84
|
const value = readFileSync(filePath, "utf-8").trim();
|
|
@@ -55,6 +87,56 @@ function readTrimmed(filePath) {
|
|
|
55
87
|
return void 0;
|
|
56
88
|
}
|
|
57
89
|
}
|
|
90
|
+
function statusUpdateFileName(kind, id) {
|
|
91
|
+
const safeId = id.replace(/[^a-z0-9-]/gi, "").slice(0, 64) || "unknown";
|
|
92
|
+
return `${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}-${kind}-${safeId}.json`;
|
|
93
|
+
}
|
|
94
|
+
function findExistingUnsentStatusUpdate(kind, id) {
|
|
95
|
+
if (!existsSync(STATUS_UPDATE_DIR)) return void 0;
|
|
96
|
+
try {
|
|
97
|
+
for (const file of readdirSync(STATUS_UPDATE_DIR).filter((f) => f.endsWith(".json"))) {
|
|
98
|
+
const filePath = path.join(STATUS_UPDATE_DIR, file);
|
|
99
|
+
const record = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
100
|
+
if (record.kind === kind && record.id === id && !record.sent_at) return filePath;
|
|
101
|
+
}
|
|
102
|
+
} catch {
|
|
103
|
+
return void 0;
|
|
104
|
+
}
|
|
105
|
+
return void 0;
|
|
106
|
+
}
|
|
107
|
+
function queueSupportStatusUpdateSync(input) {
|
|
108
|
+
const id = input.id.trim();
|
|
109
|
+
if (!id) return void 0;
|
|
110
|
+
try {
|
|
111
|
+
mkdirSync(STATUS_UPDATE_DIR, { recursive: true });
|
|
112
|
+
const existingPath = findExistingUnsentStatusUpdate(input.kind, id);
|
|
113
|
+
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
114
|
+
const filePath = existingPath ?? path.join(STATUS_UPDATE_DIR, statusUpdateFileName(input.kind, id));
|
|
115
|
+
let attempts = 0;
|
|
116
|
+
if (existingPath) {
|
|
117
|
+
try {
|
|
118
|
+
const existing = JSON.parse(readFileSync(existingPath, "utf-8"));
|
|
119
|
+
attempts = existing.attempts ?? 0;
|
|
120
|
+
} catch {
|
|
121
|
+
attempts = 0;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const record = {
|
|
125
|
+
id,
|
|
126
|
+
kind: input.kind,
|
|
127
|
+
endpointPath: input.endpointPath,
|
|
128
|
+
method: input.method ?? "PATCH",
|
|
129
|
+
payload: input.payload,
|
|
130
|
+
created_at: existingPath ? JSON.parse(readFileSync(existingPath, "utf-8")).created_at : createdAt,
|
|
131
|
+
attempts,
|
|
132
|
+
last_error: input.lastError
|
|
133
|
+
};
|
|
134
|
+
writeFileSync(filePath, JSON.stringify(record, null, 2), "utf-8");
|
|
135
|
+
return filePath;
|
|
136
|
+
} catch {
|
|
137
|
+
return void 0;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
58
140
|
function extractField(content, field) {
|
|
59
141
|
const match = content.match(new RegExp(`^${field}:\\s*(.+)$`, "m"));
|
|
60
142
|
return match?.[1]?.trim();
|
|
@@ -240,26 +322,115 @@ ${SKIPPED_MARKER}
|
|
|
240
322
|
}
|
|
241
323
|
return { sent, errors, skipped };
|
|
242
324
|
}
|
|
325
|
+
async function sendStatusUpdateRecord(record, filePath, licenseKey, licenseToken, adminToken) {
|
|
326
|
+
const endpoint = buildStatusUpdateEndpoint(record.endpointPath, adminToken);
|
|
327
|
+
const resp = await fetch(endpoint, {
|
|
328
|
+
method: record.method ?? "PATCH",
|
|
329
|
+
headers: {
|
|
330
|
+
"content-type": "application/json",
|
|
331
|
+
...adminToken ? { authorization: `Bearer ${adminToken}` } : {},
|
|
332
|
+
...!adminToken && licenseKey ? { "x-exe-license-key": licenseKey } : {},
|
|
333
|
+
...!adminToken && licenseToken ? { "x-exe-license-token": licenseToken } : {}
|
|
334
|
+
},
|
|
335
|
+
body: JSON.stringify(record.payload),
|
|
336
|
+
signal: AbortSignal.timeout(5e3)
|
|
337
|
+
});
|
|
338
|
+
if (resp.ok) {
|
|
339
|
+
writeFileSync(filePath, JSON.stringify({ ...record, sent_at: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
|
|
340
|
+
onNetworkSuccess();
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
343
|
+
writeFileSync(filePath, JSON.stringify({
|
|
344
|
+
...record,
|
|
345
|
+
attempts: (record.attempts ?? 0) + 1,
|
|
346
|
+
last_error: `HTTP ${resp.status}`,
|
|
347
|
+
last_attempt_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
348
|
+
}, null, 2), "utf-8");
|
|
349
|
+
onNetworkFailure();
|
|
350
|
+
return false;
|
|
351
|
+
}
|
|
352
|
+
async function flushStatusUpdates(licenseKey, licenseToken, adminToken, maxPerFlush) {
|
|
353
|
+
let sent = 0;
|
|
354
|
+
let errors = 0;
|
|
355
|
+
let skipped = 0;
|
|
356
|
+
if (!existsSync(STATUS_UPDATE_DIR)) return { sent, errors, skipped };
|
|
357
|
+
let files;
|
|
358
|
+
try {
|
|
359
|
+
files = readdirSync(STATUS_UPDATE_DIR).filter((f) => f.endsWith(".json")).sort();
|
|
360
|
+
} catch {
|
|
361
|
+
return { sent, errors, skipped };
|
|
362
|
+
}
|
|
363
|
+
for (const file of files) {
|
|
364
|
+
if (sent >= maxPerFlush) break;
|
|
365
|
+
if (shouldBackoff()) break;
|
|
366
|
+
const filePath = path.join(STATUS_UPDATE_DIR, file);
|
|
367
|
+
let record;
|
|
368
|
+
try {
|
|
369
|
+
record = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
370
|
+
} catch {
|
|
371
|
+
skipped++;
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
if (record.sent_at) {
|
|
375
|
+
skipped++;
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
try {
|
|
379
|
+
if (Date.now() - new Date(record.created_at).getTime() > TTL_MS) {
|
|
380
|
+
writeFileSync(filePath, JSON.stringify({
|
|
381
|
+
...record,
|
|
382
|
+
skipped_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
383
|
+
last_error: "ttl_expired"
|
|
384
|
+
}, null, 2), "utf-8");
|
|
385
|
+
skipped++;
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
} catch {
|
|
389
|
+
}
|
|
390
|
+
try {
|
|
391
|
+
const ok = await sendStatusUpdateRecord(record, filePath, licenseKey, licenseToken, adminToken);
|
|
392
|
+
if (ok) sent++;
|
|
393
|
+
else errors++;
|
|
394
|
+
} catch (err) {
|
|
395
|
+
try {
|
|
396
|
+
writeFileSync(filePath, JSON.stringify({
|
|
397
|
+
...record,
|
|
398
|
+
attempts: (record.attempts ?? 0) + 1,
|
|
399
|
+
last_error: err instanceof Error ? err.message : String(err),
|
|
400
|
+
last_attempt_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
401
|
+
}, null, 2), "utf-8");
|
|
402
|
+
} catch {
|
|
403
|
+
}
|
|
404
|
+
onNetworkFailure();
|
|
405
|
+
errors++;
|
|
406
|
+
break;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return { sent, errors, skipped };
|
|
410
|
+
}
|
|
243
411
|
async function flushSupportOutbox(opts) {
|
|
244
412
|
const maxPerFlush = opts?.maxPerFlush ?? DEFAULT_MAX_PER_FLUSH;
|
|
245
413
|
const licenseKey = loadLicenseKey();
|
|
246
414
|
const licenseToken = loadLicenseToken();
|
|
247
415
|
const adminToken = loadSupportAdminToken();
|
|
248
|
-
const [bugs, features] = await Promise.all([
|
|
416
|
+
const [bugs, features, statusUpdates] = await Promise.all([
|
|
249
417
|
flushDir(BUG_DIR, BUG_ENDPOINT, "bug", licenseKey, licenseToken, adminToken, maxPerFlush),
|
|
250
|
-
flushDir(FEATURE_DIR, FEATURE_ENDPOINT, "feature", licenseKey, licenseToken, adminToken, maxPerFlush)
|
|
418
|
+
flushDir(FEATURE_DIR, FEATURE_ENDPOINT, "feature", licenseKey, licenseToken, adminToken, maxPerFlush),
|
|
419
|
+
flushStatusUpdates(licenseKey, licenseToken, adminToken, maxPerFlush)
|
|
251
420
|
]);
|
|
252
421
|
return {
|
|
253
422
|
bugsSent: bugs.sent,
|
|
254
423
|
featuresSent: features.sent,
|
|
255
|
-
|
|
256
|
-
|
|
424
|
+
statusUpdatesSent: statusUpdates.sent,
|
|
425
|
+
errors: bugs.errors + features.errors + statusUpdates.errors,
|
|
426
|
+
skipped: bugs.skipped + features.skipped + statusUpdates.skipped
|
|
257
427
|
};
|
|
258
428
|
}
|
|
259
429
|
async function getOutboxStatus() {
|
|
260
430
|
return {
|
|
261
431
|
bugReports: scanDir(BUG_DIR),
|
|
262
|
-
featureRequests: scanDir(FEATURE_DIR)
|
|
432
|
+
featureRequests: scanDir(FEATURE_DIR),
|
|
433
|
+
statusUpdates: scanStatusDir(STATUS_UPDATE_DIR)
|
|
263
434
|
};
|
|
264
435
|
}
|
|
265
436
|
function scanDir(dir) {
|
|
@@ -288,8 +459,32 @@ function scanDir(dir) {
|
|
|
288
459
|
}
|
|
289
460
|
return { total: files.length, unsent, oldest };
|
|
290
461
|
}
|
|
462
|
+
function scanStatusDir(dir) {
|
|
463
|
+
if (!existsSync(dir)) return { total: 0, unsent: 0 };
|
|
464
|
+
let files;
|
|
465
|
+
try {
|
|
466
|
+
files = readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
467
|
+
} catch {
|
|
468
|
+
return { total: 0, unsent: 0 };
|
|
469
|
+
}
|
|
470
|
+
let unsent = 0;
|
|
471
|
+
let oldest;
|
|
472
|
+
for (const file of files) {
|
|
473
|
+
try {
|
|
474
|
+
const record = JSON.parse(readFileSync(path.join(dir, file), "utf-8"));
|
|
475
|
+
if (!record.sent_at) {
|
|
476
|
+
unsent++;
|
|
477
|
+
if (record.created_at && (!oldest || record.created_at < oldest)) oldest = record.created_at;
|
|
478
|
+
}
|
|
479
|
+
} catch {
|
|
480
|
+
unsent++;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return { total: files.length, unsent, oldest };
|
|
484
|
+
}
|
|
291
485
|
export {
|
|
292
486
|
flushSupportOutbox as flushBugReportOutbox,
|
|
293
487
|
flushSupportOutbox,
|
|
294
|
-
getOutboxStatus
|
|
488
|
+
getOutboxStatus,
|
|
489
|
+
queueSupportStatusUpdateSync
|
|
295
490
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askexenow/exe-os",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.264",
|
|
4
4
|
"description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"type": "module",
|
package/release-notes.json
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
{
|
|
2
|
-
"current": "0.9.
|
|
2
|
+
"current": "0.9.264",
|
|
3
3
|
"notes": {
|
|
4
|
+
"0.9.264": {
|
|
5
|
+
"version": "0.9.264",
|
|
6
|
+
"date": "2026-06-10",
|
|
7
|
+
"features": [],
|
|
8
|
+
"fixes": [
|
|
9
|
+
"harden support status sync"
|
|
10
|
+
],
|
|
11
|
+
"security": [
|
|
12
|
+
"release: stack 0.9.21 pins gateway v0.9.17 (Baileys rc13 — security + WA protocol fix)"
|
|
13
|
+
],
|
|
14
|
+
"other": [],
|
|
15
|
+
"migration_notes": []
|
|
16
|
+
},
|
|
17
|
+
"0.9.263": {
|
|
18
|
+
"version": "0.9.263",
|
|
19
|
+
"date": "2026-06-10",
|
|
20
|
+
"features": [],
|
|
21
|
+
"fixes": [
|
|
22
|
+
"harden diagnostics registry and projections",
|
|
23
|
+
"human-readable contact fallback for WhatsApp @lid senders"
|
|
24
|
+
],
|
|
25
|
+
"security": [],
|
|
26
|
+
"other": [],
|
|
27
|
+
"migration_notes": []
|
|
28
|
+
},
|
|
4
29
|
"0.9.262": {
|
|
5
30
|
"version": "0.9.262",
|
|
6
31
|
"date": "2026-06-10",
|
|
@@ -37,31 +62,6 @@
|
|
|
37
62
|
"security": [],
|
|
38
63
|
"other": [],
|
|
39
64
|
"migration_notes": []
|
|
40
|
-
},
|
|
41
|
-
"0.9.259": {
|
|
42
|
-
"version": "0.9.259",
|
|
43
|
-
"date": "2026-06-10",
|
|
44
|
-
"features": [
|
|
45
|
-
"GoTrue JWT auth for dashboard (Gap #32)"
|
|
46
|
-
],
|
|
47
|
-
"fixes": [],
|
|
48
|
-
"security": [],
|
|
49
|
-
"other": [],
|
|
50
|
-
"migration_notes": []
|
|
51
|
-
},
|
|
52
|
-
"0.9.258": {
|
|
53
|
-
"version": "0.9.258",
|
|
54
|
-
"date": "2026-06-10",
|
|
55
|
-
"features": [],
|
|
56
|
-
"fixes": [
|
|
57
|
-
"align filtered.conversations init schema with projection-worker source_ref dedup",
|
|
58
|
-
"keep projection-worker empty-queue test compatible with startup schema self-heal"
|
|
59
|
-
],
|
|
60
|
-
"security": [],
|
|
61
|
-
"other": [],
|
|
62
|
-
"migration_notes": [
|
|
63
|
-
"Fresh stack DBs now create filtered.conversations.source_ref with UNIQUE(platform, source_ref); existing stacks self-heal on projection-worker startup."
|
|
64
|
-
]
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
}
|
|
File without changes
|