@askexenow/exe-os 0.8.37 → 0.8.39
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/README.md +17 -8
- package/dist/bin/backfill-conversations.js +112 -70
- package/dist/bin/backfill-responses.js +53 -18
- package/dist/bin/backfill-vectors.js +43 -16
- package/dist/bin/cleanup-stale-review-tasks.js +38 -16
- package/dist/bin/cli.js +790 -468
- package/dist/bin/exe-agent.js +19 -4
- package/dist/bin/exe-assign.js +46 -13
- package/dist/bin/exe-boot.js +288 -129
- package/dist/bin/exe-call.js +20 -10
- package/dist/bin/exe-cloud.js +135 -30
- package/dist/bin/exe-dispatch.js +1 -1
- package/dist/bin/exe-doctor.js +38 -16
- package/dist/bin/exe-export-behaviors.js +43 -21
- package/dist/bin/exe-forget.js +39 -17
- package/dist/bin/exe-gateway.js +159 -50
- package/dist/bin/exe-heartbeat.js +53 -31
- package/dist/bin/exe-kill.js +40 -18
- package/dist/bin/exe-launch-agent.js +109 -36
- package/dist/bin/exe-link.js +196 -87
- package/dist/bin/exe-new-employee.js +56 -17
- package/dist/bin/exe-pending-messages.js +47 -25
- package/dist/bin/exe-pending-notifications.js +38 -16
- package/dist/bin/exe-pending-reviews.js +51 -29
- package/dist/bin/exe-rename.js +21 -7
- package/dist/bin/exe-review.js +41 -13
- package/dist/bin/exe-search.js +57 -21
- package/dist/bin/exe-session-cleanup.js +67 -31
- package/dist/bin/exe-settings.js +63 -2
- package/dist/bin/exe-status.js +35 -13
- package/dist/bin/exe-team.js +35 -13
- package/dist/bin/git-sweep.js +45 -17
- package/dist/bin/graph-backfill.js +38 -16
- package/dist/bin/graph-export.js +38 -16
- package/dist/bin/install.js +10 -1
- package/dist/bin/scan-tasks.js +47 -19
- package/dist/bin/setup.js +444 -259
- package/dist/bin/shard-migrate.js +38 -16
- package/dist/bin/wiki-sync.js +40 -17
- package/dist/gateway/index.js +113 -48
- package/dist/hooks/bug-report-worker.js +66 -39
- package/dist/hooks/commit-complete.js +45 -17
- package/dist/hooks/error-recall.js +60 -20
- package/dist/hooks/exe-heartbeat-hook.js +3 -2
- package/dist/hooks/ingest-worker.js +174 -45
- package/dist/hooks/ingest.js +74 -28
- package/dist/hooks/instructions-loaded.js +46 -17
- package/dist/hooks/notification.js +44 -15
- package/dist/hooks/post-compact.js +44 -15
- package/dist/hooks/pre-compact.js +42 -14
- package/dist/hooks/pre-tool-use.js +59 -22
- package/dist/hooks/prompt-ingest-worker.js +75 -14
- package/dist/hooks/prompt-submit.js +75 -32
- package/dist/hooks/response-ingest-worker.js +76 -15
- package/dist/hooks/session-end.js +54 -22
- package/dist/hooks/session-start.js +57 -20
- package/dist/hooks/stop.js +44 -15
- package/dist/hooks/subagent-stop.js +44 -15
- package/dist/hooks/summary-worker.js +339 -106
- package/dist/index.js +94 -23
- package/dist/lib/cloud-sync.js +191 -80
- package/dist/lib/config.js +4 -1
- package/dist/lib/consolidation.js +5 -4
- package/dist/lib/database.js +1 -0
- package/dist/lib/device-registry.js +2 -1
- package/dist/lib/embedder.js +9 -1
- package/dist/lib/employee-templates.js +5 -0
- package/dist/lib/employees.js +11 -6
- package/dist/lib/exe-daemon-client.js +6 -1
- package/dist/lib/exe-daemon.js +95 -36
- package/dist/lib/hybrid-search.js +57 -21
- package/dist/lib/identity-templates.js +16 -7
- package/dist/lib/identity.js +1 -1
- package/dist/lib/keychain.js +2 -1
- package/dist/lib/license.js +56 -6
- package/dist/lib/messaging.js +1 -1
- package/dist/lib/reminders.js +2 -2
- package/dist/lib/schedules.js +38 -16
- package/dist/lib/skill-learning.js +1 -1
- package/dist/lib/store.js +44 -16
- package/dist/lib/tasks.js +1 -1
- package/dist/lib/tmux-routing.js +1 -1
- package/dist/mcp/server.js +280 -155
- package/dist/mcp/tools/complete-reminder.js +1 -1
- package/dist/mcp/tools/create-task.js +14 -6
- package/dist/mcp/tools/deactivate-behavior.js +2 -2
- package/dist/mcp/tools/list-reminders.js +1 -1
- package/dist/mcp/tools/list-tasks.js +36 -28
- package/dist/mcp/tools/send-message.js +1 -1
- package/dist/mcp/tools/update-task.js +1 -1
- package/dist/runtime/index.js +42 -8
- package/dist/tui/App.js +220 -99
- package/package.json +5 -3
|
@@ -24,7 +24,7 @@ async function completeReminder(idOrText) {
|
|
|
24
24
|
});
|
|
25
25
|
if (result.rows.length === 0) {
|
|
26
26
|
result = await client.execute({
|
|
27
|
-
sql: `SELECT id, text FROM reminders WHERE completed_at IS NULL AND text LIKE '%' || ? || '%'`,
|
|
27
|
+
sql: `SELECT id, text FROM reminders WHERE completed_at IS NULL AND text LIKE '%' || ? || '%' LIMIT 1`,
|
|
28
28
|
args: [idOrText]
|
|
29
29
|
});
|
|
30
30
|
}
|
|
@@ -59,7 +59,7 @@ __export(config_exports, {
|
|
|
59
59
|
migrateConfig: () => migrateConfig,
|
|
60
60
|
saveConfig: () => saveConfig
|
|
61
61
|
});
|
|
62
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
62
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
63
63
|
import { readFileSync, existsSync, renameSync } from "fs";
|
|
64
64
|
import path from "path";
|
|
65
65
|
import os from "os";
|
|
@@ -185,6 +185,9 @@ async function saveConfig(config) {
|
|
|
185
185
|
await mkdir(dir, { recursive: true });
|
|
186
186
|
const configPath = path.join(dir, "config.json");
|
|
187
187
|
await writeFile(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
188
|
+
if (config.cloud?.apiKey) {
|
|
189
|
+
await chmod(configPath, 384);
|
|
190
|
+
}
|
|
188
191
|
}
|
|
189
192
|
async function loadConfigFrom(configPath) {
|
|
190
193
|
const raw = await readFile(configPath, "utf-8");
|
|
@@ -602,15 +605,20 @@ function addEmployee(employees, employee) {
|
|
|
602
605
|
}
|
|
603
606
|
return [...employees, normalized];
|
|
604
607
|
}
|
|
608
|
+
function findExeBin() {
|
|
609
|
+
try {
|
|
610
|
+
return execSync2(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
|
|
611
|
+
} catch {
|
|
612
|
+
return null;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
605
615
|
function registerBinSymlinks(name) {
|
|
606
616
|
const created = [];
|
|
607
617
|
const skipped = [];
|
|
608
618
|
const errors = [];
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
} catch {
|
|
613
|
-
errors.push("Could not find 'exe' in PATH");
|
|
619
|
+
const exeBinPath = findExeBin();
|
|
620
|
+
if (!exeBinPath) {
|
|
621
|
+
errors.push("Could not find 'exe-os' in PATH");
|
|
614
622
|
return { created, skipped, errors };
|
|
615
623
|
}
|
|
616
624
|
const binDir = path4.dirname(exeBinPath);
|
|
@@ -30,7 +30,7 @@ import { execSync as execSync2 } from "child_process";
|
|
|
30
30
|
import path2 from "path";
|
|
31
31
|
|
|
32
32
|
// src/lib/config.ts
|
|
33
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
33
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
34
34
|
import { readFileSync, existsSync, renameSync } from "fs";
|
|
35
35
|
import path from "path";
|
|
36
36
|
import os from "os";
|
|
@@ -216,7 +216,7 @@ function registerDeactivateBehavior(server) {
|
|
|
216
216
|
},
|
|
217
217
|
async ({ behavior_id }) => {
|
|
218
218
|
const caller = getActiveAgent();
|
|
219
|
-
const allowed = caller.agentId === "
|
|
219
|
+
const allowed = caller.agentId === "default" || caller.agentRole === "COO";
|
|
220
220
|
if (!allowed) {
|
|
221
221
|
return {
|
|
222
222
|
content: [{
|
|
@@ -17,7 +17,7 @@ function getClient() {
|
|
|
17
17
|
// src/lib/reminders.ts
|
|
18
18
|
async function listReminders(includeCompleted = false) {
|
|
19
19
|
const client = getClient();
|
|
20
|
-
const sql = includeCompleted ? `SELECT id, text, created_at, due_date, completed_at FROM reminders ORDER BY due_date ASC NULLS LAST` : `SELECT id, text, created_at, due_date, completed_at FROM reminders WHERE completed_at IS NULL ORDER BY due_date ASC NULLS LAST`;
|
|
20
|
+
const sql = includeCompleted ? `SELECT id, text, created_at, due_date, completed_at FROM reminders ORDER BY due_date ASC NULLS LAST LIMIT 500` : `SELECT id, text, created_at, due_date, completed_at FROM reminders WHERE completed_at IS NULL ORDER BY due_date ASC NULLS LAST LIMIT 500`;
|
|
21
21
|
const result = await client.execute(sql);
|
|
22
22
|
return result.rows.map((row) => ({
|
|
23
23
|
id: String(row.id),
|
|
@@ -28,7 +28,7 @@ var init_database = __esm({
|
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
// src/lib/config.ts
|
|
31
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
31
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
32
32
|
import { readFileSync, existsSync, renameSync } from "fs";
|
|
33
33
|
import path from "path";
|
|
34
34
|
import os from "os";
|
|
@@ -455,36 +455,44 @@ function registerListTasks(server) {
|
|
|
455
455
|
}
|
|
456
456
|
},
|
|
457
457
|
async ({ assigned_to, status, project_name, priority }) => {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
458
|
+
try {
|
|
459
|
+
const resolvedProject = project_name === "all" ? void 0 : project_name ?? getProjectName();
|
|
460
|
+
const tasks = await listTasks({
|
|
461
|
+
assignedTo: assigned_to,
|
|
462
|
+
status,
|
|
463
|
+
projectName: resolvedProject,
|
|
464
|
+
priority
|
|
465
|
+
});
|
|
466
|
+
if (tasks.length === 0) {
|
|
467
|
+
return {
|
|
468
|
+
content: [{ type: "text", text: "No tasks found." }]
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
const lines = tasks.map((t) => {
|
|
472
|
+
const cpIndicator = t.checkpointCount && t.checkpointCount > 0 ? ` [cp:${t.checkpointCount}]` : "";
|
|
473
|
+
let budgetNote = "";
|
|
474
|
+
if (t.budgetTokens !== null) {
|
|
475
|
+
const pct = Math.round(t.tokensUsed / t.budgetTokens * 100);
|
|
476
|
+
budgetNote = ` [${t.tokensUsed}/${t.budgetTokens} tokens, ${pct}%]`;
|
|
477
|
+
}
|
|
478
|
+
return `- [${t.priority.toUpperCase()}] ${t.title} (${t.projectName}) \u2014 ${t.status}${cpIndicator}${budgetNote} \u2192 ${t.assignedTo}`;
|
|
479
|
+
});
|
|
480
|
+
return {
|
|
481
|
+
content: [
|
|
482
|
+
{
|
|
483
|
+
type: "text",
|
|
484
|
+
text: `${tasks.length} task(s):
|
|
485
|
+
${lines.join("\n")}`
|
|
486
|
+
}
|
|
487
|
+
]
|
|
488
|
+
};
|
|
489
|
+
} catch (err) {
|
|
490
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
466
491
|
return {
|
|
467
|
-
content: [{ type: "text", text:
|
|
492
|
+
content: [{ type: "text", text: `Failed to list tasks: ${msg}` }],
|
|
493
|
+
isError: true
|
|
468
494
|
};
|
|
469
495
|
}
|
|
470
|
-
const lines = tasks.map((t) => {
|
|
471
|
-
const cpIndicator = t.checkpointCount && t.checkpointCount > 0 ? ` [cp:${t.checkpointCount}]` : "";
|
|
472
|
-
let budgetNote = "";
|
|
473
|
-
if (t.budgetTokens !== null) {
|
|
474
|
-
const pct = Math.round(t.tokensUsed / t.budgetTokens * 100);
|
|
475
|
-
budgetNote = ` [${t.tokensUsed}/${t.budgetTokens} tokens, ${pct}%]`;
|
|
476
|
-
}
|
|
477
|
-
return `- [${t.priority.toUpperCase()}] ${t.title} (${t.projectName}) \u2014 ${t.status}${cpIndicator}${budgetNote} \u2192 ${t.assignedTo}`;
|
|
478
|
-
});
|
|
479
|
-
return {
|
|
480
|
-
content: [
|
|
481
|
-
{
|
|
482
|
-
type: "text",
|
|
483
|
-
text: `${tasks.length} task(s):
|
|
484
|
-
${lines.join("\n")}`
|
|
485
|
-
}
|
|
486
|
-
]
|
|
487
|
-
};
|
|
488
496
|
}
|
|
489
497
|
);
|
|
490
498
|
}
|
|
@@ -342,7 +342,7 @@ var init_intercom_queue = __esm({
|
|
|
342
342
|
});
|
|
343
343
|
|
|
344
344
|
// src/lib/config.ts
|
|
345
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
345
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
346
346
|
import { readFileSync as readFileSync3, existsSync as existsSync3, renameSync as renameSync2 } from "fs";
|
|
347
347
|
import path3 from "path";
|
|
348
348
|
import os3 from "os";
|
|
@@ -44,7 +44,7 @@ var init_database = __esm({
|
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
// src/lib/config.ts
|
|
47
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
47
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
48
48
|
import { readFileSync, existsSync, renameSync } from "fs";
|
|
49
49
|
import path from "path";
|
|
50
50
|
import os from "os";
|
package/dist/runtime/index.js
CHANGED
|
@@ -461,6 +461,7 @@ async function ensureSchema() {
|
|
|
461
461
|
const client = getRawClient();
|
|
462
462
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
463
463
|
await client.execute("PRAGMA busy_timeout = 30000");
|
|
464
|
+
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
464
465
|
try {
|
|
465
466
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
466
467
|
} catch {
|
|
@@ -1269,7 +1270,7 @@ var init_database = __esm({
|
|
|
1269
1270
|
});
|
|
1270
1271
|
|
|
1271
1272
|
// src/lib/config.ts
|
|
1272
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
1273
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
1273
1274
|
import { readFileSync as readFileSync3, existsSync as existsSync3, renameSync as renameSync2 } from "fs";
|
|
1274
1275
|
import path4 from "path";
|
|
1275
1276
|
import os4 from "os";
|
|
@@ -3904,12 +3905,13 @@ var init_memory = __esm({
|
|
|
3904
3905
|
});
|
|
3905
3906
|
|
|
3906
3907
|
// src/lib/keychain.ts
|
|
3907
|
-
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod } from "fs/promises";
|
|
3908
|
+
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
3908
3909
|
import { existsSync as existsSync11 } from "fs";
|
|
3909
3910
|
import path15 from "path";
|
|
3911
|
+
import os7 from "os";
|
|
3910
3912
|
import crypto6 from "crypto";
|
|
3911
3913
|
function getKeyDir() {
|
|
3912
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path15.join(
|
|
3914
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path15.join(os7.homedir(), ".exe-os");
|
|
3913
3915
|
}
|
|
3914
3916
|
function getKeyPath() {
|
|
3915
3917
|
return path15.join(getKeyDir(), "master.key");
|
|
@@ -3966,7 +3968,7 @@ __export(shard_manager_exports, {
|
|
|
3966
3968
|
shardExists: () => shardExists
|
|
3967
3969
|
});
|
|
3968
3970
|
import path16 from "path";
|
|
3969
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync6 } from "fs";
|
|
3971
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync6, readdirSync as readdirSync3 } from "fs";
|
|
3970
3972
|
import { createClient as createClient2 } from "@libsql/client";
|
|
3971
3973
|
function initShardManager(encryptionKey) {
|
|
3972
3974
|
_encryptionKey = encryptionKey;
|
|
@@ -4005,7 +4007,6 @@ function shardExists(projectName) {
|
|
|
4005
4007
|
}
|
|
4006
4008
|
function listShards() {
|
|
4007
4009
|
if (!existsSync12(SHARDS_DIR)) return [];
|
|
4008
|
-
const { readdirSync: readdirSync3 } = __require("fs");
|
|
4009
4010
|
return readdirSync3(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
4010
4011
|
}
|
|
4011
4012
|
async function ensureShardSchema(client) {
|
|
@@ -4211,6 +4212,28 @@ __export(store_exports, {
|
|
|
4211
4212
|
vectorToBlob: () => vectorToBlob,
|
|
4212
4213
|
writeMemory: () => writeMemory
|
|
4213
4214
|
});
|
|
4215
|
+
function isBusyError2(err) {
|
|
4216
|
+
if (err instanceof Error) {
|
|
4217
|
+
const msg = err.message.toLowerCase();
|
|
4218
|
+
return msg.includes("sqlite_busy") || msg.includes("database is locked");
|
|
4219
|
+
}
|
|
4220
|
+
return false;
|
|
4221
|
+
}
|
|
4222
|
+
async function retryOnBusy2(fn, label) {
|
|
4223
|
+
for (let attempt = 0; attempt <= INIT_MAX_RETRIES; attempt++) {
|
|
4224
|
+
try {
|
|
4225
|
+
return await fn();
|
|
4226
|
+
} catch (err) {
|
|
4227
|
+
if (!isBusyError2(err) || attempt === INIT_MAX_RETRIES) throw err;
|
|
4228
|
+
process.stderr.write(
|
|
4229
|
+
`[store] SQLITE_BUSY during ${label}, retry ${attempt + 1}/${INIT_MAX_RETRIES}
|
|
4230
|
+
`
|
|
4231
|
+
);
|
|
4232
|
+
await new Promise((r) => setTimeout(r, INIT_RETRY_DELAY_MS * (attempt + 1)));
|
|
4233
|
+
}
|
|
4234
|
+
}
|
|
4235
|
+
throw new Error("unreachable");
|
|
4236
|
+
}
|
|
4214
4237
|
async function initStore(options) {
|
|
4215
4238
|
if (_flushTimer !== null) {
|
|
4216
4239
|
clearInterval(_flushTimer);
|
|
@@ -4239,14 +4262,17 @@ async function initStore(options) {
|
|
|
4239
4262
|
dbPath,
|
|
4240
4263
|
encryptionKey: hexKey
|
|
4241
4264
|
});
|
|
4242
|
-
await ensureSchema();
|
|
4265
|
+
await retryOnBusy2(() => ensureSchema(), "ensureSchema");
|
|
4243
4266
|
try {
|
|
4244
4267
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
4245
4268
|
initShardManager2(hexKey);
|
|
4246
4269
|
} catch {
|
|
4247
4270
|
}
|
|
4248
4271
|
const client = getClient();
|
|
4249
|
-
const vResult = await
|
|
4272
|
+
const vResult = await retryOnBusy2(
|
|
4273
|
+
() => client.execute("SELECT MAX(version) as max_v FROM memories"),
|
|
4274
|
+
"version-query"
|
|
4275
|
+
);
|
|
4250
4276
|
_nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
4251
4277
|
}
|
|
4252
4278
|
function classifyTier(record) {
|
|
@@ -4289,6 +4315,12 @@ async function writeMemory(record) {
|
|
|
4289
4315
|
supersedes_id: record.supersedes_id ?? null
|
|
4290
4316
|
};
|
|
4291
4317
|
_pendingRecords.push(dbRow);
|
|
4318
|
+
const MAX_PENDING = 1e3;
|
|
4319
|
+
if (_pendingRecords.length > MAX_PENDING) {
|
|
4320
|
+
const dropped = _pendingRecords.length - MAX_PENDING;
|
|
4321
|
+
_pendingRecords = _pendingRecords.slice(-MAX_PENDING);
|
|
4322
|
+
console.warn(`[store] Dropped ${dropped} oldest pending records (overflow)`);
|
|
4323
|
+
}
|
|
4292
4324
|
if (_flushTimer === null) {
|
|
4293
4325
|
_flushTimer = setInterval(() => {
|
|
4294
4326
|
void flushBatch();
|
|
@@ -4620,7 +4652,7 @@ async function getMemoryCardinality(agentId) {
|
|
|
4620
4652
|
return 0;
|
|
4621
4653
|
}
|
|
4622
4654
|
}
|
|
4623
|
-
var _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
4655
|
+
var INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
4624
4656
|
var init_store = __esm({
|
|
4625
4657
|
"src/lib/store.ts"() {
|
|
4626
4658
|
"use strict";
|
|
@@ -4628,6 +4660,8 @@ var init_store = __esm({
|
|
|
4628
4660
|
init_database();
|
|
4629
4661
|
init_keychain();
|
|
4630
4662
|
init_config();
|
|
4663
|
+
INIT_MAX_RETRIES = 3;
|
|
4664
|
+
INIT_RETRY_DELAY_MS = 1e3;
|
|
4631
4665
|
_pendingRecords = [];
|
|
4632
4666
|
_batchSize = 20;
|
|
4633
4667
|
_flushIntervalMs = 1e4;
|