@askexenow/exe-os 0.8.36 → 0.8.37
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 +9 -1
- package/dist/bin/backfill-responses.js +9 -1
- package/dist/bin/cli.js +255 -31
- package/dist/bin/exe-assign.js +9 -1
- package/dist/bin/exe-boot.js +554 -23
- package/dist/bin/exe-dispatch.js +43 -3
- package/dist/bin/exe-export-behaviors.js +7 -0
- package/dist/bin/exe-gateway.js +57 -9
- package/dist/bin/exe-heartbeat.js +2 -1
- package/dist/bin/exe-kill.js +7 -0
- package/dist/bin/exe-launch-agent.js +8 -1
- package/dist/bin/exe-link.js +503 -12
- package/dist/bin/exe-pending-messages.js +2 -1
- package/dist/bin/exe-pending-reviews.js +2 -1
- package/dist/bin/exe-review.js +9 -1
- package/dist/bin/exe-search.js +9 -1
- package/dist/bin/exe-session-cleanup.js +11 -2
- package/dist/bin/git-sweep.js +9 -1
- package/dist/bin/graph-backfill.js +7 -0
- package/dist/bin/graph-export.js +7 -0
- package/dist/bin/install.js +35 -5
- package/dist/bin/scan-tasks.js +9 -1
- package/dist/bin/shard-migrate.js +7 -0
- package/dist/bin/wiki-sync.js +7 -0
- package/dist/gateway/index.js +57 -9
- package/dist/hooks/bug-report-worker.js +45 -5
- package/dist/hooks/commit-complete.js +9 -1
- package/dist/hooks/error-recall.js +10 -2
- package/dist/hooks/exe-heartbeat-hook.js +1 -1
- package/dist/hooks/ingest-worker.js +56 -8
- package/dist/hooks/ingest.js +1 -1
- package/dist/hooks/instructions-loaded.js +10 -2
- package/dist/hooks/notification.js +10 -2
- package/dist/hooks/post-compact.js +10 -2
- package/dist/hooks/pre-compact.js +10 -2
- package/dist/hooks/pre-tool-use.js +10 -2
- package/dist/hooks/prompt-ingest-worker.js +9 -1
- package/dist/hooks/prompt-submit.js +56 -8
- package/dist/hooks/response-ingest-worker.js +9 -1
- package/dist/hooks/session-end.js +10 -2
- package/dist/hooks/session-start.js +10 -2
- package/dist/hooks/stop.js +10 -2
- package/dist/hooks/subagent-stop.js +10 -2
- package/dist/hooks/summary-worker.js +512 -13
- package/dist/index.js +65 -15
- package/dist/lib/cloud-sync.js +502 -11
- package/dist/lib/exe-daemon.js +73 -23
- package/dist/lib/hybrid-search.js +9 -1
- package/dist/lib/messaging.js +43 -3
- package/dist/lib/store.js +9 -1
- package/dist/lib/tasks.js +47 -7
- package/dist/lib/tmux-routing.js +45 -3
- package/dist/mcp/server.js +73 -16
- package/dist/mcp/tools/create-task.js +48 -8
- package/dist/mcp/tools/deactivate-behavior.js +1 -1
- package/dist/mcp/tools/list-tasks.js +2 -1
- package/dist/mcp/tools/send-message.js +46 -6
- package/dist/mcp/tools/update-task.js +3 -2
- package/dist/runtime/index.js +54 -4
- package/dist/tui/App.js +54 -4
- package/package.json +2 -2
- package/src/commands/exe/afk.md +116 -0
package/dist/bin/exe-dispatch.js
CHANGED
|
@@ -552,6 +552,42 @@ import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, mkdirSy
|
|
|
552
552
|
import path7 from "path";
|
|
553
553
|
import os4 from "os";
|
|
554
554
|
import { fileURLToPath } from "url";
|
|
555
|
+
import { unlinkSync } from "fs";
|
|
556
|
+
function spawnLockPath(sessionName) {
|
|
557
|
+
return path7.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
|
|
558
|
+
}
|
|
559
|
+
function isProcessAlive(pid) {
|
|
560
|
+
try {
|
|
561
|
+
process.kill(pid, 0);
|
|
562
|
+
return true;
|
|
563
|
+
} catch {
|
|
564
|
+
return false;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
function acquireSpawnLock(sessionName) {
|
|
568
|
+
if (!existsSync7(SPAWN_LOCK_DIR)) {
|
|
569
|
+
mkdirSync4(SPAWN_LOCK_DIR, { recursive: true });
|
|
570
|
+
}
|
|
571
|
+
const lockFile = spawnLockPath(sessionName);
|
|
572
|
+
if (existsSync7(lockFile)) {
|
|
573
|
+
try {
|
|
574
|
+
const lock = JSON.parse(readFileSync7(lockFile, "utf8"));
|
|
575
|
+
const age = Date.now() - lock.timestamp;
|
|
576
|
+
if (isProcessAlive(lock.pid) && age < 6e4) {
|
|
577
|
+
return false;
|
|
578
|
+
}
|
|
579
|
+
} catch {
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
writeFileSync4(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
|
|
583
|
+
return true;
|
|
584
|
+
}
|
|
585
|
+
function releaseSpawnLock(sessionName) {
|
|
586
|
+
try {
|
|
587
|
+
unlinkSync(spawnLockPath(sessionName));
|
|
588
|
+
} catch {
|
|
589
|
+
}
|
|
590
|
+
}
|
|
555
591
|
function resolveBehaviorsExporterScript() {
|
|
556
592
|
try {
|
|
557
593
|
const thisFile = fileURLToPath(import.meta.url);
|
|
@@ -621,10 +657,10 @@ function isEmployeeAlive(sessionName) {
|
|
|
621
657
|
}
|
|
622
658
|
function findFreeInstance(employeeName2, exeSession2, maxInstances = 10, isAlive = isEmployeeAlive) {
|
|
623
659
|
const base = employeeSessionName(employeeName2, exeSession2);
|
|
624
|
-
if (!isAlive(base)) return 0;
|
|
660
|
+
if (!isAlive(base) && acquireSpawnLock(base)) return 0;
|
|
625
661
|
for (let i = 2; i <= maxInstances; i++) {
|
|
626
662
|
const candidate = employeeSessionName(employeeName2, exeSession2, i);
|
|
627
|
-
if (!isAlive(candidate)) return i;
|
|
663
|
+
if (!isAlive(candidate) && acquireSpawnLock(candidate)) return i;
|
|
628
664
|
}
|
|
629
665
|
return null;
|
|
630
666
|
}
|
|
@@ -936,6 +972,7 @@ function spawnEmployee(employeeName2, exeSession2, projectDir2, opts) {
|
|
|
936
972
|
command: spawnCommand
|
|
937
973
|
});
|
|
938
974
|
if (spawnResult.error) {
|
|
975
|
+
releaseSpawnLock(sessionName);
|
|
939
976
|
return { sessionName, error: `tmux new-session failed: ${spawnResult.error}` };
|
|
940
977
|
}
|
|
941
978
|
transport.pipeLog(sessionName, logFile);
|
|
@@ -973,6 +1010,7 @@ function spawnEmployee(employeeName2, exeSession2, projectDir2, opts) {
|
|
|
973
1010
|
}
|
|
974
1011
|
}
|
|
975
1012
|
if (!booted) {
|
|
1013
|
+
releaseSpawnLock(sessionName);
|
|
976
1014
|
return { sessionName, error: `${useExeAgent ? "exe-agent" : "claude"} did not boot within 15s` };
|
|
977
1015
|
}
|
|
978
1016
|
if (!useExeAgent) {
|
|
@@ -989,9 +1027,10 @@ function spawnEmployee(employeeName2, exeSession2, projectDir2, opts) {
|
|
|
989
1027
|
pid: 0,
|
|
990
1028
|
registeredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
991
1029
|
});
|
|
1030
|
+
releaseSpawnLock(sessionName);
|
|
992
1031
|
return { sessionName };
|
|
993
1032
|
}
|
|
994
|
-
var SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
|
|
1033
|
+
var SPAWN_LOCK_DIR, SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
|
|
995
1034
|
var init_tmux_routing = __esm({
|
|
996
1035
|
"src/lib/tmux-routing.ts"() {
|
|
997
1036
|
"use strict";
|
|
@@ -1003,6 +1042,7 @@ var init_tmux_routing = __esm({
|
|
|
1003
1042
|
init_provider_table();
|
|
1004
1043
|
init_intercom_queue();
|
|
1005
1044
|
init_plan_limits();
|
|
1045
|
+
SPAWN_LOCK_DIR = path7.join(os4.homedir(), ".exe-os", "spawn-locks");
|
|
1006
1046
|
SESSION_CACHE = path7.join(os4.homedir(), ".exe-os", "session-cache");
|
|
1007
1047
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
1008
1048
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
@@ -1424,6 +1424,13 @@ async function flushBatch() {
|
|
|
1424
1424
|
_flushing = true;
|
|
1425
1425
|
try {
|
|
1426
1426
|
const batch = _pendingRecords.slice(0);
|
|
1427
|
+
const client = getClient();
|
|
1428
|
+
const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
|
|
1429
|
+
let baseVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
1430
|
+
for (const row of batch) {
|
|
1431
|
+
row.version = baseVersion++;
|
|
1432
|
+
}
|
|
1433
|
+
_nextVersion = baseVersion;
|
|
1427
1434
|
const buildStmt = (row) => {
|
|
1428
1435
|
const hasVector = row.vector !== null;
|
|
1429
1436
|
const taskId = row.task_id ?? null;
|
package/dist/bin/exe-gateway.js
CHANGED
|
@@ -2200,7 +2200,8 @@ async function writeMemory(record) {
|
|
|
2200
2200
|
has_error: record.has_error ? 1 : 0,
|
|
2201
2201
|
raw_text: record.raw_text,
|
|
2202
2202
|
vector: record.vector,
|
|
2203
|
-
version:
|
|
2203
|
+
version: 0,
|
|
2204
|
+
// Placeholder — assigned atomically at flush time
|
|
2204
2205
|
task_id: record.task_id ?? null,
|
|
2205
2206
|
importance: record.importance ?? 5,
|
|
2206
2207
|
status: record.status ?? "active",
|
|
@@ -2234,6 +2235,13 @@ async function flushBatch() {
|
|
|
2234
2235
|
_flushing = true;
|
|
2235
2236
|
try {
|
|
2236
2237
|
const batch = _pendingRecords.slice(0);
|
|
2238
|
+
const client = getClient();
|
|
2239
|
+
const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
|
|
2240
|
+
let baseVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
2241
|
+
for (const row of batch) {
|
|
2242
|
+
row.version = baseVersion++;
|
|
2243
|
+
}
|
|
2244
|
+
_nextVersion = baseVersion;
|
|
2237
2245
|
const buildStmt = (row) => {
|
|
2238
2246
|
const hasVector = row.vector !== null;
|
|
2239
2247
|
const taskId = row.task_id ?? null;
|
|
@@ -4690,6 +4698,42 @@ import { readFileSync as readFileSync9, writeFileSync as writeFileSync4, mkdirSy
|
|
|
4690
4698
|
import path11 from "path";
|
|
4691
4699
|
import os4 from "os";
|
|
4692
4700
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
4701
|
+
import { unlinkSync as unlinkSync2 } from "fs";
|
|
4702
|
+
function spawnLockPath(sessionName) {
|
|
4703
|
+
return path11.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
|
|
4704
|
+
}
|
|
4705
|
+
function isProcessAlive(pid) {
|
|
4706
|
+
try {
|
|
4707
|
+
process.kill(pid, 0);
|
|
4708
|
+
return true;
|
|
4709
|
+
} catch {
|
|
4710
|
+
return false;
|
|
4711
|
+
}
|
|
4712
|
+
}
|
|
4713
|
+
function acquireSpawnLock2(sessionName) {
|
|
4714
|
+
if (!existsSync10(SPAWN_LOCK_DIR)) {
|
|
4715
|
+
mkdirSync6(SPAWN_LOCK_DIR, { recursive: true });
|
|
4716
|
+
}
|
|
4717
|
+
const lockFile = spawnLockPath(sessionName);
|
|
4718
|
+
if (existsSync10(lockFile)) {
|
|
4719
|
+
try {
|
|
4720
|
+
const lock = JSON.parse(readFileSync9(lockFile, "utf8"));
|
|
4721
|
+
const age = Date.now() - lock.timestamp;
|
|
4722
|
+
if (isProcessAlive(lock.pid) && age < 6e4) {
|
|
4723
|
+
return false;
|
|
4724
|
+
}
|
|
4725
|
+
} catch {
|
|
4726
|
+
}
|
|
4727
|
+
}
|
|
4728
|
+
writeFileSync4(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
|
|
4729
|
+
return true;
|
|
4730
|
+
}
|
|
4731
|
+
function releaseSpawnLock2(sessionName) {
|
|
4732
|
+
try {
|
|
4733
|
+
unlinkSync2(spawnLockPath(sessionName));
|
|
4734
|
+
} catch {
|
|
4735
|
+
}
|
|
4736
|
+
}
|
|
4693
4737
|
function resolveBehaviorsExporterScript() {
|
|
4694
4738
|
try {
|
|
4695
4739
|
const thisFile = fileURLToPath2(import.meta.url);
|
|
@@ -4770,10 +4814,10 @@ function isEmployeeAlive(sessionName) {
|
|
|
4770
4814
|
}
|
|
4771
4815
|
function findFreeInstance(employeeName, exeSession, maxInstances = 10, isAlive = isEmployeeAlive) {
|
|
4772
4816
|
const base = employeeSessionName(employeeName, exeSession);
|
|
4773
|
-
if (!isAlive(base)) return 0;
|
|
4817
|
+
if (!isAlive(base) && acquireSpawnLock2(base)) return 0;
|
|
4774
4818
|
for (let i = 2; i <= maxInstances; i++) {
|
|
4775
4819
|
const candidate = employeeSessionName(employeeName, exeSession, i);
|
|
4776
|
-
if (!isAlive(candidate)) return i;
|
|
4820
|
+
if (!isAlive(candidate) && acquireSpawnLock2(candidate)) return i;
|
|
4777
4821
|
}
|
|
4778
4822
|
return null;
|
|
4779
4823
|
}
|
|
@@ -5107,6 +5151,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
5107
5151
|
command: spawnCommand
|
|
5108
5152
|
});
|
|
5109
5153
|
if (spawnResult.error) {
|
|
5154
|
+
releaseSpawnLock2(sessionName);
|
|
5110
5155
|
return { sessionName, error: `tmux new-session failed: ${spawnResult.error}` };
|
|
5111
5156
|
}
|
|
5112
5157
|
transport.pipeLog(sessionName, logFile);
|
|
@@ -5144,6 +5189,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
5144
5189
|
}
|
|
5145
5190
|
}
|
|
5146
5191
|
if (!booted) {
|
|
5192
|
+
releaseSpawnLock2(sessionName);
|
|
5147
5193
|
return { sessionName, error: `${useExeAgent ? "exe-agent" : "claude"} did not boot within 15s` };
|
|
5148
5194
|
}
|
|
5149
5195
|
if (!useExeAgent) {
|
|
@@ -5160,9 +5206,10 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
5160
5206
|
pid: 0,
|
|
5161
5207
|
registeredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5162
5208
|
});
|
|
5209
|
+
releaseSpawnLock2(sessionName);
|
|
5163
5210
|
return { sessionName };
|
|
5164
5211
|
}
|
|
5165
|
-
var SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
|
|
5212
|
+
var SPAWN_LOCK_DIR, SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
|
|
5166
5213
|
var init_tmux_routing = __esm({
|
|
5167
5214
|
"src/lib/tmux-routing.ts"() {
|
|
5168
5215
|
"use strict";
|
|
@@ -5174,6 +5221,7 @@ var init_tmux_routing = __esm({
|
|
|
5174
5221
|
init_provider_table();
|
|
5175
5222
|
init_intercom_queue();
|
|
5176
5223
|
init_plan_limits();
|
|
5224
|
+
SPAWN_LOCK_DIR = path11.join(os4.homedir(), ".exe-os", "spawn-locks");
|
|
5177
5225
|
SESSION_CACHE = path11.join(os4.homedir(), ".exe-os", "session-cache");
|
|
5178
5226
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
5179
5227
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
@@ -5441,7 +5489,7 @@ import os5 from "os";
|
|
|
5441
5489
|
import {
|
|
5442
5490
|
readFileSync as readFileSync10,
|
|
5443
5491
|
readdirSync,
|
|
5444
|
-
unlinkSync as
|
|
5492
|
+
unlinkSync as unlinkSync3,
|
|
5445
5493
|
existsSync as existsSync11,
|
|
5446
5494
|
rmdirSync
|
|
5447
5495
|
} from "fs";
|
|
@@ -5889,7 +5937,7 @@ var init_tasks_crud = __esm({
|
|
|
5889
5937
|
|
|
5890
5938
|
// src/lib/tasks-review.ts
|
|
5891
5939
|
import path14 from "path";
|
|
5892
|
-
import { existsSync as existsSync13, readdirSync as readdirSync2, unlinkSync as
|
|
5940
|
+
import { existsSync as existsSync13, readdirSync as readdirSync2, unlinkSync as unlinkSync4 } from "fs";
|
|
5893
5941
|
async function countPendingReviews() {
|
|
5894
5942
|
const client = getClient();
|
|
5895
5943
|
const result = await client.execute({
|
|
@@ -6013,7 +6061,7 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
|
|
|
6013
6061
|
if (existsSync13(cacheDir)) {
|
|
6014
6062
|
for (const f of readdirSync2(cacheDir)) {
|
|
6015
6063
|
if (f.startsWith("review-notified-")) {
|
|
6016
|
-
|
|
6064
|
+
unlinkSync4(path14.join(cacheDir, f));
|
|
6017
6065
|
}
|
|
6018
6066
|
}
|
|
6019
6067
|
}
|
|
@@ -6614,7 +6662,7 @@ __export(tasks_exports, {
|
|
|
6614
6662
|
writeCheckpoint: () => writeCheckpoint
|
|
6615
6663
|
});
|
|
6616
6664
|
import path17 from "path";
|
|
6617
|
-
import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync7, unlinkSync as
|
|
6665
|
+
import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync7, unlinkSync as unlinkSync5 } from "fs";
|
|
6618
6666
|
async function createTask(input) {
|
|
6619
6667
|
const result = await createTaskCore(input);
|
|
6620
6668
|
if (!input.skipDispatch && result.status !== "blocked" && !process.env.VITEST) {
|
|
@@ -6640,7 +6688,7 @@ async function updateTask(input) {
|
|
|
6640
6688
|
writeFileSync5(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
|
|
6641
6689
|
} else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled") {
|
|
6642
6690
|
try {
|
|
6643
|
-
|
|
6691
|
+
unlinkSync5(cachePath);
|
|
6644
6692
|
} catch {
|
|
6645
6693
|
}
|
|
6646
6694
|
}
|
|
@@ -1501,7 +1501,7 @@ var init_plan_limits = __esm({
|
|
|
1501
1501
|
import path11 from "path";
|
|
1502
1502
|
import os5 from "os";
|
|
1503
1503
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1504
|
-
var SESSION_CACHE, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS;
|
|
1504
|
+
var SPAWN_LOCK_DIR, SESSION_CACHE, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS;
|
|
1505
1505
|
var init_tmux_routing = __esm({
|
|
1506
1506
|
"src/lib/tmux-routing.ts"() {
|
|
1507
1507
|
"use strict";
|
|
@@ -1513,6 +1513,7 @@ var init_tmux_routing = __esm({
|
|
|
1513
1513
|
init_provider_table();
|
|
1514
1514
|
init_intercom_queue();
|
|
1515
1515
|
init_plan_limits();
|
|
1516
|
+
SPAWN_LOCK_DIR = path11.join(os5.homedir(), ".exe-os", "spawn-locks");
|
|
1516
1517
|
SESSION_CACHE = path11.join(os5.homedir(), ".exe-os", "session-cache");
|
|
1517
1518
|
INTERCOM_LOG2 = path11.join(os5.homedir(), ".exe-os", "intercom.log");
|
|
1518
1519
|
DEBOUNCE_FILE = path11.join(SESSION_CACHE, "intercom-debounce.json");
|
package/dist/bin/exe-kill.js
CHANGED
|
@@ -1427,6 +1427,13 @@ async function flushBatch() {
|
|
|
1427
1427
|
_flushing = true;
|
|
1428
1428
|
try {
|
|
1429
1429
|
const batch = _pendingRecords.slice(0);
|
|
1430
|
+
const client = getClient();
|
|
1431
|
+
const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
|
|
1432
|
+
let baseVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
1433
|
+
for (const row of batch) {
|
|
1434
|
+
row.version = baseVersion++;
|
|
1435
|
+
}
|
|
1436
|
+
_nextVersion = baseVersion;
|
|
1430
1437
|
const buildStmt = (row) => {
|
|
1431
1438
|
const hasVector = row.vector !== null;
|
|
1432
1439
|
const taskId = row.task_id ?? null;
|
|
@@ -1295,7 +1295,7 @@ function getActiveAgent() {
|
|
|
1295
1295
|
"tmux display-message -p '#{session_name}' 2>/dev/null",
|
|
1296
1296
|
{ encoding: "utf8", timeout: 2e3 }
|
|
1297
1297
|
).trim();
|
|
1298
|
-
const empMatch = sessionName.match(/^(
|
|
1298
|
+
const empMatch = sessionName.match(/^([a-zA-Z]+)\d*-exe\d+$/);
|
|
1299
1299
|
if (empMatch && empMatch[1] !== "exe") {
|
|
1300
1300
|
return { agentId: empMatch[1], agentRole: "employee" };
|
|
1301
1301
|
}
|
|
@@ -2351,6 +2351,13 @@ async function flushBatch() {
|
|
|
2351
2351
|
_flushing = true;
|
|
2352
2352
|
try {
|
|
2353
2353
|
const batch = _pendingRecords.slice(0);
|
|
2354
|
+
const client = getClient();
|
|
2355
|
+
const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
|
|
2356
|
+
let baseVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
2357
|
+
for (const row of batch) {
|
|
2358
|
+
row.version = baseVersion++;
|
|
2359
|
+
}
|
|
2360
|
+
_nextVersion = baseVersion;
|
|
2354
2361
|
const buildStmt = (row) => {
|
|
2355
2362
|
const hasVector = row.vector !== null;
|
|
2356
2363
|
const taskId = row.task_id ?? null;
|