@askexenow/exe-os 0.8.0 → 0.8.1
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 +178 -79
- package/dist/bin/backfill-responses.js +160 -8
- package/dist/bin/backfill-vectors.js +130 -1
- package/dist/bin/cleanup-stale-review-tasks.js +130 -1
- package/dist/bin/cli.js +10111 -7540
- package/dist/bin/exe-agent.js +159 -1
- package/dist/bin/exe-assign.js +235 -16
- package/dist/bin/exe-boot.js +344 -472
- package/dist/bin/exe-call.js +145 -1
- package/dist/bin/exe-cloud.js +11 -0
- package/dist/bin/exe-dispatch.js +37 -24
- package/dist/bin/exe-doctor.js +130 -1
- package/dist/bin/exe-export-behaviors.js +150 -7
- package/dist/bin/exe-forget.js +822 -665
- package/dist/bin/exe-gateway.js +470 -62
- package/dist/bin/exe-heartbeat.js +133 -2
- package/dist/bin/exe-kill.js +150 -7
- package/dist/bin/exe-launch-agent.js +150 -7
- package/dist/bin/exe-new-employee.js +756 -224
- package/dist/bin/exe-pending-messages.js +132 -2
- package/dist/bin/exe-pending-notifications.js +130 -1
- package/dist/bin/exe-pending-reviews.js +132 -2
- package/dist/bin/exe-review.js +160 -8
- package/dist/bin/exe-search.js +2473 -2008
- package/dist/bin/exe-session-cleanup.js +238 -51
- package/dist/bin/exe-settings.js +11 -0
- package/dist/bin/exe-status.js +130 -1
- package/dist/bin/exe-team.js +130 -1
- package/dist/bin/git-sweep.js +272 -16
- package/dist/bin/graph-backfill.js +150 -7
- package/dist/bin/graph-export.js +150 -7
- package/dist/bin/install.js +5 -0
- package/dist/bin/scan-tasks.js +238 -19
- package/dist/bin/setup.js +1776 -10
- package/dist/bin/shard-migrate.js +150 -7
- package/dist/bin/update.js +9 -6
- package/dist/bin/wiki-sync.js +150 -7
- package/dist/gateway/index.js +470 -62
- package/dist/hooks/bug-report-worker.js +195 -35
- package/dist/hooks/commit-complete.js +272 -16
- package/dist/hooks/error-recall.js +2313 -1847
- package/dist/hooks/exe-heartbeat-hook.js +5 -0
- package/dist/hooks/ingest-worker.js +330 -58
- package/dist/hooks/ingest.js +11 -0
- package/dist/hooks/instructions-loaded.js +199 -10
- package/dist/hooks/notification.js +199 -10
- package/dist/hooks/post-compact.js +199 -10
- package/dist/hooks/pre-compact.js +199 -10
- package/dist/hooks/pre-tool-use.js +199 -10
- package/dist/hooks/prompt-ingest-worker.js +179 -14
- package/dist/hooks/prompt-submit.js +781 -285
- package/dist/hooks/response-ingest-worker.js +1900 -1405
- package/dist/hooks/session-end.js +456 -12
- package/dist/hooks/session-start.js +2188 -1724
- package/dist/hooks/stop.js +200 -10
- package/dist/hooks/subagent-stop.js +199 -10
- package/dist/hooks/summary-worker.js +604 -334
- package/dist/index.js +554 -61
- package/dist/lib/cloud-sync.js +5 -0
- package/dist/lib/config.js +13 -0
- package/dist/lib/consolidation.js +5 -0
- package/dist/lib/database.js +104 -0
- package/dist/lib/device-registry.js +109 -0
- package/dist/lib/embedder.js +13 -0
- package/dist/lib/employee-templates.js +53 -26
- package/dist/lib/employees.js +5 -0
- package/dist/lib/exe-daemon-client.js +5 -0
- package/dist/lib/exe-daemon.js +493 -79
- package/dist/lib/file-grep.js +20 -4
- package/dist/lib/hybrid-search.js +1435 -190
- package/dist/lib/identity-templates.js +126 -5
- package/dist/lib/identity.js +5 -0
- package/dist/lib/license.js +5 -0
- package/dist/lib/messaging.js +37 -24
- package/dist/lib/schedules.js +130 -1
- package/dist/lib/skill-learning.js +11 -0
- package/dist/lib/status-brief.js +5 -0
- package/dist/lib/store.js +199 -10
- package/dist/lib/task-router.js +72 -6
- package/dist/lib/tasks.js +179 -50
- package/dist/lib/tmux-routing.js +179 -46
- package/dist/mcp/server.js +2129 -1855
- package/dist/mcp/tools/create-task.js +86 -36
- package/dist/mcp/tools/deactivate-behavior.js +5 -0
- package/dist/mcp/tools/list-tasks.js +39 -11
- package/dist/mcp/tools/send-message.js +37 -24
- package/dist/mcp/tools/update-task.js +153 -38
- package/dist/runtime/index.js +451 -59
- package/dist/tui/App.js +454 -59
- package/package.json +1 -1
package/dist/bin/git-sweep.js
CHANGED
|
@@ -245,6 +245,27 @@ async function ensureSchema() {
|
|
|
245
245
|
});
|
|
246
246
|
} catch {
|
|
247
247
|
}
|
|
248
|
+
try {
|
|
249
|
+
await client.execute({
|
|
250
|
+
sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
|
|
251
|
+
args: []
|
|
252
|
+
});
|
|
253
|
+
} catch {
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
await client.execute({
|
|
257
|
+
sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
|
|
258
|
+
args: []
|
|
259
|
+
});
|
|
260
|
+
} catch {
|
|
261
|
+
}
|
|
262
|
+
try {
|
|
263
|
+
await client.execute({
|
|
264
|
+
sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
|
|
265
|
+
args: []
|
|
266
|
+
});
|
|
267
|
+
} catch {
|
|
268
|
+
}
|
|
248
269
|
try {
|
|
249
270
|
await client.execute({
|
|
250
271
|
sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
|
|
@@ -655,6 +676,15 @@ async function ensureSchema() {
|
|
|
655
676
|
} catch {
|
|
656
677
|
}
|
|
657
678
|
}
|
|
679
|
+
for (const col of [
|
|
680
|
+
"ALTER TABLE memories ADD COLUMN source_path TEXT",
|
|
681
|
+
"ALTER TABLE memories ADD COLUMN source_type TEXT DEFAULT 'text'"
|
|
682
|
+
]) {
|
|
683
|
+
try {
|
|
684
|
+
await client.execute(col);
|
|
685
|
+
} catch {
|
|
686
|
+
}
|
|
687
|
+
}
|
|
658
688
|
await client.executeMultiple(`
|
|
659
689
|
CREATE INDEX IF NOT EXISTS idx_memories_workspace
|
|
660
690
|
ON memories(workspace_id);
|
|
@@ -719,6 +749,34 @@ async function ensureSchema() {
|
|
|
719
749
|
CREATE INDEX IF NOT EXISTS idx_conversations_channel
|
|
720
750
|
ON conversations(channel_id);
|
|
721
751
|
`);
|
|
752
|
+
try {
|
|
753
|
+
await client.execute({
|
|
754
|
+
sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
|
|
755
|
+
args: []
|
|
756
|
+
});
|
|
757
|
+
} catch {
|
|
758
|
+
}
|
|
759
|
+
try {
|
|
760
|
+
await client.execute({
|
|
761
|
+
sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
|
|
762
|
+
args: []
|
|
763
|
+
});
|
|
764
|
+
} catch {
|
|
765
|
+
}
|
|
766
|
+
try {
|
|
767
|
+
await client.execute({
|
|
768
|
+
sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
|
|
769
|
+
args: []
|
|
770
|
+
});
|
|
771
|
+
} catch {
|
|
772
|
+
}
|
|
773
|
+
try {
|
|
774
|
+
await client.execute({
|
|
775
|
+
sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
|
|
776
|
+
args: []
|
|
777
|
+
});
|
|
778
|
+
} catch {
|
|
779
|
+
}
|
|
722
780
|
await client.executeMultiple(`
|
|
723
781
|
CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
|
|
724
782
|
content_text,
|
|
@@ -745,6 +803,52 @@ async function ensureSchema() {
|
|
|
745
803
|
VALUES (new.rowid, new.content_text, new.sender_name, new.agent_response);
|
|
746
804
|
END;
|
|
747
805
|
`);
|
|
806
|
+
try {
|
|
807
|
+
await client.execute({
|
|
808
|
+
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
809
|
+
args: []
|
|
810
|
+
});
|
|
811
|
+
} catch {
|
|
812
|
+
}
|
|
813
|
+
try {
|
|
814
|
+
await client.execute(
|
|
815
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
|
|
816
|
+
);
|
|
817
|
+
} catch {
|
|
818
|
+
}
|
|
819
|
+
try {
|
|
820
|
+
await client.execute({
|
|
821
|
+
sql: `UPDATE memories SET tier = 1 WHERE tool_name = 'commit_to_long_term_memory' AND importance >= 8 AND tier = 3`,
|
|
822
|
+
args: []
|
|
823
|
+
});
|
|
824
|
+
await client.execute({
|
|
825
|
+
sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
|
|
826
|
+
args: []
|
|
827
|
+
});
|
|
828
|
+
} catch {
|
|
829
|
+
}
|
|
830
|
+
try {
|
|
831
|
+
await client.execute({
|
|
832
|
+
sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
|
|
833
|
+
args: []
|
|
834
|
+
});
|
|
835
|
+
} catch {
|
|
836
|
+
}
|
|
837
|
+
try {
|
|
838
|
+
await client.execute(
|
|
839
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
|
|
840
|
+
);
|
|
841
|
+
} catch {
|
|
842
|
+
}
|
|
843
|
+
for (const col of [
|
|
844
|
+
"ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
|
|
845
|
+
"ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER DEFAULT 0"
|
|
846
|
+
]) {
|
|
847
|
+
try {
|
|
848
|
+
await client.execute(col);
|
|
849
|
+
} catch {
|
|
850
|
+
}
|
|
851
|
+
}
|
|
748
852
|
}
|
|
749
853
|
async function disposeDatabase() {
|
|
750
854
|
if (_client) {
|
|
@@ -877,6 +981,11 @@ function normalizeSessionLifecycle(raw) {
|
|
|
877
981
|
const userSL = raw.sessionLifecycle ?? {};
|
|
878
982
|
raw.sessionLifecycle = { ...defaultSL, ...userSL };
|
|
879
983
|
}
|
|
984
|
+
function normalizeAutoUpdate(raw) {
|
|
985
|
+
const defaultAU = DEFAULT_CONFIG.autoUpdate;
|
|
986
|
+
const userAU = raw.autoUpdate ?? {};
|
|
987
|
+
raw.autoUpdate = { ...defaultAU, ...userAU };
|
|
988
|
+
}
|
|
880
989
|
async function loadConfig() {
|
|
881
990
|
const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
|
|
882
991
|
await mkdir2(dir, { recursive: true });
|
|
@@ -899,6 +1008,7 @@ async function loadConfig() {
|
|
|
899
1008
|
}
|
|
900
1009
|
normalizeScalingRoadmap(migratedCfg);
|
|
901
1010
|
normalizeSessionLifecycle(migratedCfg);
|
|
1011
|
+
normalizeAutoUpdate(migratedCfg);
|
|
902
1012
|
const config = { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db"), ...migratedCfg };
|
|
903
1013
|
if (config.dbPath.startsWith("~")) {
|
|
904
1014
|
config.dbPath = config.dbPath.replace(/^~/, os.homedir());
|
|
@@ -974,6 +1084,11 @@ var init_config = __esm({
|
|
|
974
1084
|
idleKillTicksRequired: 3,
|
|
975
1085
|
idleKillIntercomAckWindowMs: 1e4,
|
|
976
1086
|
maxAutoInstances: 10
|
|
1087
|
+
},
|
|
1088
|
+
autoUpdate: {
|
|
1089
|
+
checkOnBoot: true,
|
|
1090
|
+
autoInstall: false,
|
|
1091
|
+
checkIntervalMs: 24 * 60 * 60 * 1e3
|
|
977
1092
|
}
|
|
978
1093
|
};
|
|
979
1094
|
CONFIG_MIGRATIONS = [
|
|
@@ -1107,13 +1222,27 @@ async function ensureShardSchema(client) {
|
|
|
1107
1222
|
"ALTER TABLE memories ADD COLUMN document_id TEXT",
|
|
1108
1223
|
"ALTER TABLE memories ADD COLUMN user_id TEXT",
|
|
1109
1224
|
"ALTER TABLE memories ADD COLUMN char_offset INTEGER",
|
|
1110
|
-
"ALTER TABLE memories ADD COLUMN page_number INTEGER"
|
|
1225
|
+
"ALTER TABLE memories ADD COLUMN page_number INTEGER",
|
|
1226
|
+
// Source provenance columns (must match database.ts)
|
|
1227
|
+
"ALTER TABLE memories ADD COLUMN source_path TEXT",
|
|
1228
|
+
"ALTER TABLE memories ADD COLUMN source_type TEXT DEFAULT 'text'",
|
|
1229
|
+
"ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3",
|
|
1230
|
+
"ALTER TABLE memories ADD COLUMN supersedes_id TEXT"
|
|
1111
1231
|
]) {
|
|
1112
1232
|
try {
|
|
1113
1233
|
await client.execute(col);
|
|
1114
1234
|
} catch {
|
|
1115
1235
|
}
|
|
1116
1236
|
}
|
|
1237
|
+
for (const idx of [
|
|
1238
|
+
"CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)",
|
|
1239
|
+
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL"
|
|
1240
|
+
]) {
|
|
1241
|
+
try {
|
|
1242
|
+
await client.execute(idx);
|
|
1243
|
+
} catch {
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1117
1246
|
try {
|
|
1118
1247
|
await client.execute("CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)");
|
|
1119
1248
|
} catch {
|
|
@@ -1222,8 +1351,11 @@ var store_exports = {};
|
|
|
1222
1351
|
__export(store_exports, {
|
|
1223
1352
|
attachDocumentMetadata: () => attachDocumentMetadata,
|
|
1224
1353
|
buildWikiScopeFilter: () => buildWikiScopeFilter,
|
|
1354
|
+
classifyTier: () => classifyTier,
|
|
1225
1355
|
disposeStore: () => disposeStore,
|
|
1226
1356
|
flushBatch: () => flushBatch,
|
|
1357
|
+
flushTier3: () => flushTier3,
|
|
1358
|
+
getMemoryCardinality: () => getMemoryCardinality,
|
|
1227
1359
|
initStore: () => initStore,
|
|
1228
1360
|
reserveVersions: () => reserveVersions,
|
|
1229
1361
|
searchMemories: () => searchMemories,
|
|
@@ -1269,6 +1401,11 @@ async function initStore(options) {
|
|
|
1269
1401
|
const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
|
|
1270
1402
|
_nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
1271
1403
|
}
|
|
1404
|
+
function classifyTier(record) {
|
|
1405
|
+
if (record.tool_name === "commit_to_long_term_memory" && (record.importance ?? 0) >= 8) return 1;
|
|
1406
|
+
if (["store_memory", "manual"].includes(record.tool_name ?? "") && (record.importance ?? 0) >= 5) return 2;
|
|
1407
|
+
return 3;
|
|
1408
|
+
}
|
|
1272
1409
|
async function writeMemory(record) {
|
|
1273
1410
|
if (record.vector !== null && record.vector.length !== EMBEDDING_DIM) {
|
|
1274
1411
|
throw new Error(
|
|
@@ -1296,7 +1433,11 @@ async function writeMemory(record) {
|
|
|
1296
1433
|
document_id: record.document_id ?? null,
|
|
1297
1434
|
user_id: record.user_id ?? null,
|
|
1298
1435
|
char_offset: record.char_offset ?? null,
|
|
1299
|
-
page_number: record.page_number ?? null
|
|
1436
|
+
page_number: record.page_number ?? null,
|
|
1437
|
+
source_path: record.source_path ?? null,
|
|
1438
|
+
source_type: record.source_type ?? null,
|
|
1439
|
+
tier: record.tier ?? classifyTier(record),
|
|
1440
|
+
supersedes_id: record.supersedes_id ?? null
|
|
1300
1441
|
};
|
|
1301
1442
|
_pendingRecords.push(dbRow);
|
|
1302
1443
|
if (_flushTimer === null) {
|
|
@@ -1328,20 +1469,26 @@ async function flushBatch() {
|
|
|
1328
1469
|
const userId = row.user_id ?? null;
|
|
1329
1470
|
const charOffset = row.char_offset ?? null;
|
|
1330
1471
|
const pageNumber = row.page_number ?? null;
|
|
1472
|
+
const sourcePath = row.source_path ?? null;
|
|
1473
|
+
const sourceType = row.source_type ?? null;
|
|
1474
|
+
const tier = row.tier ?? 3;
|
|
1475
|
+
const supersedesId = row.supersedes_id ?? null;
|
|
1331
1476
|
return {
|
|
1332
1477
|
sql: hasVector ? `INSERT OR IGNORE INTO memories
|
|
1333
1478
|
(id, agent_id, agent_role, session_id, timestamp,
|
|
1334
1479
|
tool_name, project_name,
|
|
1335
1480
|
has_error, raw_text, vector, version, task_id, importance, status,
|
|
1336
1481
|
confidence, last_accessed,
|
|
1337
|
-
workspace_id, document_id, user_id, char_offset, page_number
|
|
1338
|
-
|
|
1482
|
+
workspace_id, document_id, user_id, char_offset, page_number,
|
|
1483
|
+
source_path, source_type, tier, supersedes_id)
|
|
1484
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories
|
|
1339
1485
|
(id, agent_id, agent_role, session_id, timestamp,
|
|
1340
1486
|
tool_name, project_name,
|
|
1341
1487
|
has_error, raw_text, vector, version, task_id, importance, status,
|
|
1342
1488
|
confidence, last_accessed,
|
|
1343
|
-
workspace_id, document_id, user_id, char_offset, page_number
|
|
1344
|
-
|
|
1489
|
+
workspace_id, document_id, user_id, char_offset, page_number,
|
|
1490
|
+
source_path, source_type, tier, supersedes_id)
|
|
1491
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
1345
1492
|
args: hasVector ? [
|
|
1346
1493
|
row.id,
|
|
1347
1494
|
row.agent_id,
|
|
@@ -1363,7 +1510,11 @@ async function flushBatch() {
|
|
|
1363
1510
|
documentId,
|
|
1364
1511
|
userId,
|
|
1365
1512
|
charOffset,
|
|
1366
|
-
pageNumber
|
|
1513
|
+
pageNumber,
|
|
1514
|
+
sourcePath,
|
|
1515
|
+
sourceType,
|
|
1516
|
+
tier,
|
|
1517
|
+
supersedesId
|
|
1367
1518
|
] : [
|
|
1368
1519
|
row.id,
|
|
1369
1520
|
row.agent_id,
|
|
@@ -1384,7 +1535,11 @@ async function flushBatch() {
|
|
|
1384
1535
|
documentId,
|
|
1385
1536
|
userId,
|
|
1386
1537
|
charOffset,
|
|
1387
|
-
pageNumber
|
|
1538
|
+
pageNumber,
|
|
1539
|
+
sourcePath,
|
|
1540
|
+
sourceType,
|
|
1541
|
+
tier,
|
|
1542
|
+
supersedesId
|
|
1388
1543
|
]
|
|
1389
1544
|
};
|
|
1390
1545
|
};
|
|
@@ -1458,7 +1613,8 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
1458
1613
|
has_error, raw_text, vector, importance, status,
|
|
1459
1614
|
confidence, last_accessed,
|
|
1460
1615
|
workspace_id, document_id, user_id,
|
|
1461
|
-
char_offset, page_number
|
|
1616
|
+
char_offset, page_number,
|
|
1617
|
+
source_path, source_type
|
|
1462
1618
|
FROM memories
|
|
1463
1619
|
WHERE agent_id = ?
|
|
1464
1620
|
AND vector IS NOT NULL${statusFilter}
|
|
@@ -1507,7 +1663,9 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
1507
1663
|
document_id: row.document_id ?? null,
|
|
1508
1664
|
user_id: row.user_id ?? null,
|
|
1509
1665
|
char_offset: row.char_offset ?? null,
|
|
1510
|
-
page_number: row.page_number ?? null
|
|
1666
|
+
page_number: row.page_number ?? null,
|
|
1667
|
+
source_path: row.source_path ?? null,
|
|
1668
|
+
source_type: row.source_type ?? null
|
|
1511
1669
|
}));
|
|
1512
1670
|
}
|
|
1513
1671
|
async function attachDocumentMetadata(records) {
|
|
@@ -1545,6 +1703,25 @@ async function attachDocumentMetadata(records) {
|
|
|
1545
1703
|
}
|
|
1546
1704
|
return records;
|
|
1547
1705
|
}
|
|
1706
|
+
async function flushTier3(agentId, options) {
|
|
1707
|
+
const client = getClient();
|
|
1708
|
+
const maxAge = options?.maxAgeHours ?? 72;
|
|
1709
|
+
const cutoff = new Date(Date.now() - maxAge * 36e5).toISOString();
|
|
1710
|
+
if (options?.dryRun) {
|
|
1711
|
+
const result2 = await client.execute({
|
|
1712
|
+
sql: `SELECT COUNT(*) as cnt FROM memories
|
|
1713
|
+
WHERE agent_id = ? AND tier = 3 AND status = 'active' AND timestamp < ?`,
|
|
1714
|
+
args: [agentId, cutoff]
|
|
1715
|
+
});
|
|
1716
|
+
return { archived: Number(result2.rows[0]?.cnt ?? 0) };
|
|
1717
|
+
}
|
|
1718
|
+
const result = await client.execute({
|
|
1719
|
+
sql: `UPDATE memories SET status = 'archived'
|
|
1720
|
+
WHERE agent_id = ? AND tier = 3 AND status = 'active' AND timestamp < ?`,
|
|
1721
|
+
args: [agentId, cutoff]
|
|
1722
|
+
});
|
|
1723
|
+
return { archived: result.rowsAffected };
|
|
1724
|
+
}
|
|
1548
1725
|
async function disposeStore() {
|
|
1549
1726
|
if (_flushTimer !== null) {
|
|
1550
1727
|
clearInterval(_flushTimer);
|
|
@@ -1575,6 +1752,18 @@ function reserveVersions(count) {
|
|
|
1575
1752
|
}
|
|
1576
1753
|
return reserved;
|
|
1577
1754
|
}
|
|
1755
|
+
async function getMemoryCardinality(agentId) {
|
|
1756
|
+
try {
|
|
1757
|
+
const client = getClient();
|
|
1758
|
+
const result = await client.execute({
|
|
1759
|
+
sql: `SELECT COUNT(*) as cnt FROM memories WHERE agent_id = ? AND COALESCE(status, 'active') = 'active'`,
|
|
1760
|
+
args: [agentId]
|
|
1761
|
+
});
|
|
1762
|
+
return Number(result.rows[0]?.cnt) || 0;
|
|
1763
|
+
} catch {
|
|
1764
|
+
return 0;
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1578
1767
|
var _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
1579
1768
|
var init_store = __esm({
|
|
1580
1769
|
"src/lib/store.ts"() {
|
|
@@ -1605,13 +1794,44 @@ __export(tasks_crud_exports, {
|
|
|
1605
1794
|
listTasks: () => listTasks,
|
|
1606
1795
|
resolveTask: () => resolveTask,
|
|
1607
1796
|
slugify: () => slugify,
|
|
1608
|
-
updateTaskStatus: () => updateTaskStatus
|
|
1797
|
+
updateTaskStatus: () => updateTaskStatus,
|
|
1798
|
+
writeCheckpoint: () => writeCheckpoint
|
|
1609
1799
|
});
|
|
1610
1800
|
import crypto2 from "crypto";
|
|
1611
1801
|
import path4 from "path";
|
|
1612
1802
|
import { execSync } from "child_process";
|
|
1613
1803
|
import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
|
|
1614
1804
|
import { existsSync as existsSync4, readFileSync as readFileSync2 } from "fs";
|
|
1805
|
+
async function writeCheckpoint(input) {
|
|
1806
|
+
const client = getClient();
|
|
1807
|
+
const row = await resolveTask(client, input.taskId);
|
|
1808
|
+
const taskId = String(row.id);
|
|
1809
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1810
|
+
const blockedByIds = [];
|
|
1811
|
+
if (row.blocked_by) {
|
|
1812
|
+
blockedByIds.push(String(row.blocked_by));
|
|
1813
|
+
}
|
|
1814
|
+
const checkpoint = {
|
|
1815
|
+
step: input.step,
|
|
1816
|
+
context_summary: input.contextSummary,
|
|
1817
|
+
files_touched: input.filesTouched ?? [],
|
|
1818
|
+
blocked_by_ids: blockedByIds,
|
|
1819
|
+
last_checkpoint_at: now
|
|
1820
|
+
};
|
|
1821
|
+
const result = await client.execute({
|
|
1822
|
+
sql: `UPDATE tasks SET checkpoint = ?, checkpoint_count = checkpoint_count + 1, updated_at = ? WHERE id = ?`,
|
|
1823
|
+
args: [JSON.stringify(checkpoint), now, taskId]
|
|
1824
|
+
});
|
|
1825
|
+
if (result.rowsAffected === 0) {
|
|
1826
|
+
throw new Error(`Checkpoint write failed: task ${taskId} not found`);
|
|
1827
|
+
}
|
|
1828
|
+
const countResult = await client.execute({
|
|
1829
|
+
sql: "SELECT checkpoint_count FROM tasks WHERE id = ?",
|
|
1830
|
+
args: [taskId]
|
|
1831
|
+
});
|
|
1832
|
+
const checkpointCount = Number(countResult.rows[0]?.checkpoint_count ?? 1);
|
|
1833
|
+
return { checkpointCount };
|
|
1834
|
+
}
|
|
1615
1835
|
function extractParentFromContext(contextBody) {
|
|
1616
1836
|
if (!contextBody) return null;
|
|
1617
1837
|
const match = contextBody.match(
|
|
@@ -1718,9 +1938,10 @@ async function createTaskCore(input) {
|
|
|
1718
1938
|
} catch {
|
|
1719
1939
|
}
|
|
1720
1940
|
}
|
|
1941
|
+
const complexity = input.complexity ?? "standard";
|
|
1721
1942
|
await client.execute({
|
|
1722
|
-
sql: `INSERT INTO tasks (id, title, assigned_to, assigned_by, project_name, priority, status, task_file, blocked_by, parent_task_id, reviewer, context, created_at, updated_at)
|
|
1723
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
1943
|
+
sql: `INSERT INTO tasks (id, title, assigned_to, assigned_by, project_name, priority, status, task_file, blocked_by, parent_task_id, reviewer, context, complexity, budget_tokens, budget_fallback_model, tokens_used, tokens_warned_at, created_at, updated_at)
|
|
1944
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
1724
1945
|
args: [
|
|
1725
1946
|
id,
|
|
1726
1947
|
input.title,
|
|
@@ -1734,6 +1955,11 @@ async function createTaskCore(input) {
|
|
|
1734
1955
|
parentTaskId,
|
|
1735
1956
|
input.reviewer ?? null,
|
|
1736
1957
|
input.context,
|
|
1958
|
+
input.budgetTokens ?? null,
|
|
1959
|
+
input.budgetFallbackModel ?? null,
|
|
1960
|
+
0,
|
|
1961
|
+
null,
|
|
1962
|
+
complexity,
|
|
1737
1963
|
now,
|
|
1738
1964
|
now
|
|
1739
1965
|
]
|
|
@@ -1749,7 +1975,11 @@ async function createTaskCore(input) {
|
|
|
1749
1975
|
taskFile,
|
|
1750
1976
|
createdAt: now,
|
|
1751
1977
|
updatedAt: now,
|
|
1752
|
-
warning
|
|
1978
|
+
warning,
|
|
1979
|
+
budgetTokens: input.budgetTokens ?? null,
|
|
1980
|
+
budgetFallbackModel: input.budgetFallbackModel ?? null,
|
|
1981
|
+
tokensUsed: 0,
|
|
1982
|
+
tokensWarnedAt: null
|
|
1753
1983
|
};
|
|
1754
1984
|
}
|
|
1755
1985
|
async function listTasks(input) {
|
|
@@ -1789,7 +2019,12 @@ async function listTasks(input) {
|
|
|
1789
2019
|
status: String(r.status),
|
|
1790
2020
|
taskFile: String(r.task_file),
|
|
1791
2021
|
createdAt: String(r.created_at),
|
|
1792
|
-
updatedAt: String(r.updated_at)
|
|
2022
|
+
updatedAt: String(r.updated_at),
|
|
2023
|
+
checkpointCount: Number(r.checkpoint_count ?? 0),
|
|
2024
|
+
budgetTokens: r.budget_tokens !== null ? Number(r.budget_tokens) : null,
|
|
2025
|
+
budgetFallbackModel: r.budget_fallback_model !== null ? String(r.budget_fallback_model) : null,
|
|
2026
|
+
tokensUsed: Number(r.tokens_used ?? 0),
|
|
2027
|
+
tokensWarnedAt: r.tokens_warned_at !== null ? Number(r.tokens_warned_at) : null
|
|
1793
2028
|
}));
|
|
1794
2029
|
}
|
|
1795
2030
|
function checkStaleCompletion(taskContext, taskCreatedAt) {
|
|
@@ -1797,8 +2032,13 @@ function checkStaleCompletion(taskContext, taskCreatedAt) {
|
|
|
1797
2032
|
if (!DELEGATION_KEYWORDS.test(taskContext)) return null;
|
|
1798
2033
|
try {
|
|
1799
2034
|
const since = new Date(taskCreatedAt).toISOString();
|
|
2035
|
+
const branch = execSync(
|
|
2036
|
+
"git rev-parse --abbrev-ref HEAD 2>/dev/null",
|
|
2037
|
+
{ encoding: "utf8", timeout: 3e3 }
|
|
2038
|
+
).trim();
|
|
2039
|
+
const branchArg = branch && branch !== "HEAD" ? branch : "";
|
|
1800
2040
|
const commitCount = execSync(
|
|
1801
|
-
`git log --oneline --since="${since}" 2>/dev/null | wc -l`,
|
|
2041
|
+
`git log --oneline --since="${since}" ${branchArg} 2>/dev/null | wc -l`,
|
|
1802
2042
|
{ encoding: "utf8", timeout: 5e3 }
|
|
1803
2043
|
).trim();
|
|
1804
2044
|
const count = parseInt(commitCount, 10);
|
|
@@ -1857,6 +2097,14 @@ ${input.result}` : `\u26A0\uFE0F ${warning}`;
|
|
|
1857
2097
|
const claimedBy = cur?.assigned_tmux ? ` (claimed by ${cur.assigned_tmux})` : "";
|
|
1858
2098
|
throw new Error(`${TASK_ALREADY_CLAIMED_PREFIX}: task ${taskId} is ${status}${claimedBy}`);
|
|
1859
2099
|
}
|
|
2100
|
+
try {
|
|
2101
|
+
await writeCheckpoint({
|
|
2102
|
+
taskId,
|
|
2103
|
+
step: "claimed",
|
|
2104
|
+
contextSummary: `Task claimed by session. Transitioning open \u2192 in_progress.`
|
|
2105
|
+
});
|
|
2106
|
+
} catch {
|
|
2107
|
+
}
|
|
1860
2108
|
return { row, taskFile, now, taskId };
|
|
1861
2109
|
}
|
|
1862
2110
|
if (input.result) {
|
|
@@ -1870,6 +2118,14 @@ ${input.result}` : `\u26A0\uFE0F ${warning}`;
|
|
|
1870
2118
|
args: [input.status, now, taskId]
|
|
1871
2119
|
});
|
|
1872
2120
|
}
|
|
2121
|
+
try {
|
|
2122
|
+
await writeCheckpoint({
|
|
2123
|
+
taskId,
|
|
2124
|
+
step: `status_transition:${input.status}`,
|
|
2125
|
+
contextSummary: input.result ? `Transitioned to ${input.status}. Result: ${input.result.slice(0, 500)}` : `Transitioned to ${input.status}.`
|
|
2126
|
+
});
|
|
2127
|
+
} catch {
|
|
2128
|
+
}
|
|
1873
2129
|
return { row, taskFile, now, taskId };
|
|
1874
2130
|
}
|
|
1875
2131
|
async function deleteTaskCore(taskId, _baseDir) {
|