@askexenow/exe-os 0.9.63 → 0.9.64
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/cli.js +43 -111
- package/dist/bin/exe-doctor.js +1154 -2588
- package/dist/bin/exe-new-employee.js +1 -111
- package/dist/bin/exe-start-codex.js +1 -111
- package/dist/bin/exe-start-opencode.js +1 -125
- package/dist/bin/install.js +1 -111
- package/dist/bin/stack-update.js +42 -0
- package/dist/hooks/bug-report-worker.js +42 -111
- package/dist/hooks/pre-compact.js +109 -236
- package/dist/hooks/session-end.js +122 -137
- package/dist/hooks/summary-worker.js +72 -124
- package/dist/lib/exe-daemon.js +5 -356
- package/dist/mcp/server.js +5 -372
- package/package.json +1 -1
|
@@ -8892,98 +8892,54 @@ async function fastDbInit() {
|
|
|
8892
8892
|
// src/adapters/claude/hooks/bug-report-worker.ts
|
|
8893
8893
|
init_database();
|
|
8894
8894
|
init_tasks();
|
|
8895
|
-
|
|
8896
|
-
|
|
8897
|
-
|
|
8898
|
-
|
|
8899
|
-
|
|
8900
|
-
|
|
8901
|
-
|
|
8902
|
-
|
|
8903
|
-
|
|
8904
|
-
|
|
8905
|
-
|
|
8906
|
-
|
|
8907
|
-
|
|
8908
|
-
|
|
8909
|
-
|
|
8910
|
-
|
|
8911
|
-
|
|
8912
|
-
|
|
8913
|
-
|
|
8914
|
-
|
|
8915
|
-
|
|
8916
|
-
|
|
8917
|
-
|
|
8918
|
-
const summary = firstMeaningfulLine(errorText);
|
|
8919
|
-
const fingerprint = input.fingerprint && input.fingerprint.trim().length > 0 ? input.fingerprint.trim() : stableFingerprint(input);
|
|
8920
|
-
return {
|
|
8921
|
-
schemaVersion: BUG_INTAKE_SCHEMA_VERSION,
|
|
8922
|
-
id: randomUUID4(),
|
|
8923
|
-
source: input.source,
|
|
8924
|
-
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
8925
|
-
fingerprint,
|
|
8926
|
-
severity: input.severity ?? "p1",
|
|
8927
|
-
title: `[auto-bug] ${toolName}: ${summary.slice(0, 60)}`,
|
|
8928
|
-
summary,
|
|
8929
|
-
reporterAgentId: input.reporterAgentId ?? "unknown",
|
|
8930
|
-
reporterAgentRole: input.reporterAgentRole ?? "employee",
|
|
8931
|
-
projectName: input.projectName ?? "unknown",
|
|
8932
|
-
toolName,
|
|
8933
|
-
errorText,
|
|
8934
|
-
toolInput: input.toolInput ?? "{}",
|
|
8935
|
-
runtime: input.runtime,
|
|
8936
|
-
repo: input.repo,
|
|
8937
|
-
licenseKeyHash: hashLicense(input.licenseKey),
|
|
8938
|
-
labels: ["auto-bug", input.source, toolName].filter(Boolean)
|
|
8939
|
-
};
|
|
8940
|
-
}
|
|
8941
|
-
function buildBugIntakeFromEnv(env = process.env) {
|
|
8942
|
-
return buildBugIntake({
|
|
8943
|
-
source: "hook",
|
|
8944
|
-
toolName: env.BUG_TOOL_NAME,
|
|
8945
|
-
errorText: env.BUG_ERROR_TEXT,
|
|
8946
|
-
toolInput: env.BUG_TOOL_INPUT,
|
|
8947
|
-
fingerprint: env.BUG_FINGERPRINT,
|
|
8948
|
-
reporterAgentId: env.BUG_AGENT_ID,
|
|
8949
|
-
reporterAgentRole: env.BUG_AGENT_ROLE,
|
|
8950
|
-
projectName: env.BUG_PROJECT_NAME,
|
|
8951
|
-
runtime: env.EXE_RUNTIME,
|
|
8952
|
-
repo: env.EXE_REPO,
|
|
8953
|
-
licenseKey: env.EXE_LICENSE_KEY
|
|
8895
|
+
async function main() {
|
|
8896
|
+
const toolName = process.env.BUG_TOOL_NAME ?? "unknown";
|
|
8897
|
+
const errorText = process.env.BUG_ERROR_TEXT ?? "";
|
|
8898
|
+
const toolInput = process.env.BUG_TOOL_INPUT ?? "{}";
|
|
8899
|
+
const fingerprint = process.env.BUG_FINGERPRINT ?? "";
|
|
8900
|
+
const agentId = process.env.BUG_AGENT_ID ?? "unknown";
|
|
8901
|
+
const agentRole = process.env.BUG_AGENT_ROLE ?? "employee";
|
|
8902
|
+
const projectName = process.env.BUG_PROJECT_NAME ?? "unknown";
|
|
8903
|
+
await fastDbInit();
|
|
8904
|
+
const fpPrefix = fingerprint.slice(0, 8);
|
|
8905
|
+
const client = getClient();
|
|
8906
|
+
const { loadEmployeesSync: loadEmployeesSync2, getEmployeeByRole: getEmployeeByRole2, getCoordinatorName: getCoordinatorName2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
8907
|
+
const employees = loadEmployeesSync2();
|
|
8908
|
+
const coordinatorName = getCoordinatorName2(employees);
|
|
8909
|
+
const ctoName = getEmployeeByRole2(employees, "CTO")?.name ?? coordinatorName;
|
|
8910
|
+
const existing = await client.execute({
|
|
8911
|
+
sql: `SELECT id FROM tasks
|
|
8912
|
+
WHERE assigned_to = ?
|
|
8913
|
+
AND status IN ('open', 'in_progress')
|
|
8914
|
+
AND title LIKE '[auto-bug]%'
|
|
8915
|
+
AND task_file LIKE ?
|
|
8916
|
+
LIMIT 1`,
|
|
8917
|
+
args: [ctoName, `%${fpPrefix}%`]
|
|
8954
8918
|
});
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8919
|
+
if (existing.rows.length > 0) {
|
|
8920
|
+
process.stderr.write(`[bug-report-worker] Duplicate found for fingerprint ${fingerprint}, skipping
|
|
8921
|
+
`);
|
|
8922
|
+
return;
|
|
8923
|
+
}
|
|
8924
|
+
const errorSummary = errorText.split("\n").find((line) => line.trim().length > 0)?.trim().slice(0, 60) ?? "unknown error";
|
|
8925
|
+
const context = [
|
|
8958
8926
|
"## Auto-detected system bug",
|
|
8959
8927
|
"",
|
|
8960
|
-
`**
|
|
8961
|
-
`**
|
|
8962
|
-
`**
|
|
8963
|
-
`**
|
|
8964
|
-
`**Timestamp:** ${record.createdAt}`,
|
|
8965
|
-
`**Fingerprint:** ${record.fingerprint}`,
|
|
8966
|
-
`**Severity:** ${record.severity}`,
|
|
8967
|
-
record.runtime ? `**Runtime:** ${record.runtime}` : void 0,
|
|
8968
|
-
record.repo ? `**Repo:** ${record.repo}` : void 0,
|
|
8969
|
-
record.licenseKeyHash ? `**License hash:** ${record.licenseKeyHash}` : void 0,
|
|
8928
|
+
`**Detected by:** ${agentId} (${agentRole})`,
|
|
8929
|
+
`**Tool:** ${toolName}`,
|
|
8930
|
+
`**Timestamp:** ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
8931
|
+
`**Fingerprint:** ${fingerprint}`,
|
|
8970
8932
|
"",
|
|
8971
8933
|
"## Error output",
|
|
8972
8934
|
"",
|
|
8973
8935
|
"```",
|
|
8974
|
-
|
|
8936
|
+
errorText.slice(0, 1e3),
|
|
8975
8937
|
"```",
|
|
8976
8938
|
"",
|
|
8977
8939
|
"## Tool input (reproduction context)",
|
|
8978
8940
|
"",
|
|
8979
8941
|
"```json",
|
|
8980
|
-
|
|
8981
|
-
"```",
|
|
8982
|
-
"",
|
|
8983
|
-
"## Normalized intake JSON",
|
|
8984
|
-
"",
|
|
8985
|
-
"```json",
|
|
8986
|
-
JSON.stringify(record, null, 2),
|
|
8942
|
+
toolInput.slice(0, 500),
|
|
8987
8943
|
"```",
|
|
8988
8944
|
"",
|
|
8989
8945
|
"## Triage notes",
|
|
@@ -8991,44 +8947,19 @@ function formatBugIntakeTaskContext(record) {
|
|
|
8991
8947
|
"- Classification: system bug (auto-detected)",
|
|
8992
8948
|
"- Review this error \u2014 fix if real, close if false positive",
|
|
8993
8949
|
"- If false positive: add the error pattern to USER_ERROR_PATTERNS in error-detector.ts"
|
|
8994
|
-
].
|
|
8995
|
-
}
|
|
8996
|
-
|
|
8997
|
-
// src/adapters/claude/hooks/bug-report-worker.ts
|
|
8998
|
-
async function main() {
|
|
8999
|
-
const intake = buildBugIntakeFromEnv(process.env);
|
|
9000
|
-
await fastDbInit();
|
|
9001
|
-
const client = getClient();
|
|
9002
|
-
const { loadEmployeesSync: loadEmployeesSync2, getEmployeeByRole: getEmployeeByRole2, getCoordinatorName: getCoordinatorName2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
9003
|
-
const employees = loadEmployeesSync2();
|
|
9004
|
-
const coordinatorName = getCoordinatorName2(employees);
|
|
9005
|
-
const ctoName = getEmployeeByRole2(employees, "CTO")?.name ?? coordinatorName;
|
|
9006
|
-
const existing = await client.execute({
|
|
9007
|
-
sql: `SELECT id FROM tasks
|
|
9008
|
-
WHERE assigned_to = ?
|
|
9009
|
-
AND status IN ('open', 'in_progress')
|
|
9010
|
-
AND title LIKE '[auto-bug]%'
|
|
9011
|
-
AND (context LIKE ? OR task_file LIKE ?)
|
|
9012
|
-
LIMIT 1`,
|
|
9013
|
-
args: [ctoName, `%${intake.fingerprint}%`, `%${intake.fingerprint.slice(0, 8)}%`]
|
|
9014
|
-
});
|
|
9015
|
-
if (existing.rows.length > 0) {
|
|
9016
|
-
process.stderr.write(`[bug-report-worker] Duplicate found for fingerprint ${intake.fingerprint}, skipping
|
|
9017
|
-
`);
|
|
9018
|
-
return;
|
|
9019
|
-
}
|
|
8950
|
+
].join("\n");
|
|
9020
8951
|
await createTask({
|
|
9021
|
-
title:
|
|
8952
|
+
title: `[auto-bug] ${toolName}: ${errorSummary}`,
|
|
9022
8953
|
assignedTo: ctoName,
|
|
9023
8954
|
assignedBy: "system",
|
|
9024
|
-
projectName
|
|
9025
|
-
priority:
|
|
9026
|
-
context
|
|
8955
|
+
projectName,
|
|
8956
|
+
priority: "p1",
|
|
8957
|
+
context,
|
|
9027
8958
|
baseDir: process.cwd(),
|
|
9028
8959
|
skipDispatch: true,
|
|
9029
8960
|
reviewer: coordinatorName
|
|
9030
8961
|
});
|
|
9031
|
-
process.stderr.write(`[bug-report-worker] Created auto-bug task for ${
|
|
8962
|
+
process.stderr.write(`[bug-report-worker] Created auto-bug task for ${toolName}: ${errorSummary}
|
|
9032
8963
|
`);
|
|
9033
8964
|
}
|
|
9034
8965
|
main().catch((err) => {
|
|
@@ -6725,15 +6725,15 @@ var init_task_scope = __esm({
|
|
|
6725
6725
|
|
|
6726
6726
|
// src/lib/keychain.ts
|
|
6727
6727
|
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
6728
|
-
import { existsSync as
|
|
6728
|
+
import { existsSync as existsSync16 } from "fs";
|
|
6729
6729
|
import { execSync as execSync8 } from "child_process";
|
|
6730
|
-
import
|
|
6730
|
+
import path20 from "path";
|
|
6731
6731
|
import os12 from "os";
|
|
6732
6732
|
function getKeyDir() {
|
|
6733
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ??
|
|
6733
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path20.join(os12.homedir(), ".exe-os");
|
|
6734
6734
|
}
|
|
6735
6735
|
function getKeyPath() {
|
|
6736
|
-
return
|
|
6736
|
+
return path20.join(getKeyDir(), "master.key");
|
|
6737
6737
|
}
|
|
6738
6738
|
function macKeychainGet() {
|
|
6739
6739
|
if (process.platform !== "darwin") return null;
|
|
@@ -6881,7 +6881,7 @@ async function getMasterKey() {
|
|
|
6881
6881
|
}
|
|
6882
6882
|
}
|
|
6883
6883
|
const keyPath = getKeyPath();
|
|
6884
|
-
if (!
|
|
6884
|
+
if (!existsSync16(keyPath)) {
|
|
6885
6885
|
process.stderr.write(
|
|
6886
6886
|
`[keychain] Key not found at ${keyPath} (HOME=${os12.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
6887
6887
|
`
|
|
@@ -7155,12 +7155,12 @@ __export(shard_manager_exports, {
|
|
|
7155
7155
|
listShards: () => listShards,
|
|
7156
7156
|
shardExists: () => shardExists
|
|
7157
7157
|
});
|
|
7158
|
-
import
|
|
7159
|
-
import { existsSync as
|
|
7158
|
+
import path21 from "path";
|
|
7159
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync9, readdirSync as readdirSync5, renameSync as renameSync4, statSync as statSync2 } from "fs";
|
|
7160
7160
|
import { createClient as createClient2 } from "@libsql/client";
|
|
7161
7161
|
function initShardManager(encryptionKey) {
|
|
7162
7162
|
_encryptionKey = encryptionKey;
|
|
7163
|
-
if (!
|
|
7163
|
+
if (!existsSync17(SHARDS_DIR)) {
|
|
7164
7164
|
mkdirSync9(SHARDS_DIR, { recursive: true });
|
|
7165
7165
|
}
|
|
7166
7166
|
_shardingEnabled = true;
|
|
@@ -7190,7 +7190,7 @@ function getShardClient(projectName) {
|
|
|
7190
7190
|
while (_shards.size >= MAX_OPEN_SHARDS) {
|
|
7191
7191
|
evictLRU();
|
|
7192
7192
|
}
|
|
7193
|
-
const dbPath =
|
|
7193
|
+
const dbPath = path21.join(SHARDS_DIR, `${safeName}.db`);
|
|
7194
7194
|
const client = createClient2({
|
|
7195
7195
|
url: `file:${dbPath}`,
|
|
7196
7196
|
encryptionKey: _encryptionKey
|
|
@@ -7201,13 +7201,13 @@ function getShardClient(projectName) {
|
|
|
7201
7201
|
}
|
|
7202
7202
|
function shardExists(projectName) {
|
|
7203
7203
|
const safeName = safeShardName(projectName);
|
|
7204
|
-
return
|
|
7204
|
+
return existsSync17(path21.join(SHARDS_DIR, `${safeName}.db`));
|
|
7205
7205
|
}
|
|
7206
7206
|
function safeShardName(projectName) {
|
|
7207
7207
|
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7208
7208
|
}
|
|
7209
7209
|
function listShards() {
|
|
7210
|
-
if (!
|
|
7210
|
+
if (!existsSync17(SHARDS_DIR)) return [];
|
|
7211
7211
|
return readdirSync5(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
7212
7212
|
}
|
|
7213
7213
|
async function auditShardHealth(options = {}) {
|
|
@@ -7219,8 +7219,8 @@ async function auditShardHealth(options = {}) {
|
|
|
7219
7219
|
const names = listShards();
|
|
7220
7220
|
const shards = [];
|
|
7221
7221
|
for (const name of names) {
|
|
7222
|
-
const dbPath =
|
|
7223
|
-
const stat =
|
|
7222
|
+
const dbPath = path21.join(SHARDS_DIR, `${name}.db`);
|
|
7223
|
+
const stat = statSync2(dbPath);
|
|
7224
7224
|
const item = {
|
|
7225
7225
|
name,
|
|
7226
7226
|
path: dbPath,
|
|
@@ -7254,8 +7254,8 @@ async function auditShardHealth(options = {}) {
|
|
|
7254
7254
|
_shards.delete(name);
|
|
7255
7255
|
_shardLastAccess.delete(name);
|
|
7256
7256
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7257
|
-
const archivedPath =
|
|
7258
|
-
|
|
7257
|
+
const archivedPath = path21.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
|
|
7258
|
+
renameSync4(dbPath, archivedPath);
|
|
7259
7259
|
item.archivedPath = archivedPath;
|
|
7260
7260
|
}
|
|
7261
7261
|
} finally {
|
|
@@ -7471,12 +7471,12 @@ async function getReadyShardClient(projectName) {
|
|
|
7471
7471
|
client.close();
|
|
7472
7472
|
_shards.delete(safeName);
|
|
7473
7473
|
_shardLastAccess.delete(safeName);
|
|
7474
|
-
const dbPath =
|
|
7475
|
-
if (
|
|
7476
|
-
const stat =
|
|
7474
|
+
const dbPath = path21.join(SHARDS_DIR, `${safeName}.db`);
|
|
7475
|
+
if (existsSync17(dbPath)) {
|
|
7476
|
+
const stat = statSync2(dbPath);
|
|
7477
7477
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7478
|
-
const archivedPath =
|
|
7479
|
-
|
|
7478
|
+
const archivedPath = path21.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
7479
|
+
renameSync4(dbPath, archivedPath);
|
|
7480
7480
|
process.stderr.write(
|
|
7481
7481
|
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
|
|
7482
7482
|
`
|
|
@@ -7543,7 +7543,7 @@ var init_shard_manager = __esm({
|
|
|
7543
7543
|
"src/lib/shard-manager.ts"() {
|
|
7544
7544
|
"use strict";
|
|
7545
7545
|
init_config();
|
|
7546
|
-
SHARDS_DIR =
|
|
7546
|
+
SHARDS_DIR = path21.join(EXE_AI_DIR, "shards");
|
|
7547
7547
|
SHARD_IDLE_MS = 5 * 60 * 1e3;
|
|
7548
7548
|
MAX_OPEN_SHARDS = 10;
|
|
7549
7549
|
EVICTION_INTERVAL_MS = 60 * 1e3;
|
|
@@ -8658,6 +8658,78 @@ var init_fast_db_init = __esm({
|
|
|
8658
8658
|
}
|
|
8659
8659
|
});
|
|
8660
8660
|
|
|
8661
|
+
// src/lib/memory-queue.ts
|
|
8662
|
+
import { appendFileSync as appendFileSync2, readFileSync as readFileSync14, renameSync as renameSync5, unlinkSync as unlinkSync8, existsSync as existsSync18, statSync as statSync3 } from "fs";
|
|
8663
|
+
import path22 from "path";
|
|
8664
|
+
function enqueueMemory(entry) {
|
|
8665
|
+
appendFileSync2(QUEUE_PATH2, JSON.stringify(entry) + "\n");
|
|
8666
|
+
}
|
|
8667
|
+
var QUEUE_PATH2, PROCESSING_PATH, TTL_MS2;
|
|
8668
|
+
var init_memory_queue = __esm({
|
|
8669
|
+
"src/lib/memory-queue.ts"() {
|
|
8670
|
+
"use strict";
|
|
8671
|
+
init_config();
|
|
8672
|
+
QUEUE_PATH2 = path22.join(EXE_AI_DIR, "memory-queue.jsonl");
|
|
8673
|
+
PROCESSING_PATH = QUEUE_PATH2 + ".processing";
|
|
8674
|
+
TTL_MS2 = 24 * 60 * 60 * 1e3;
|
|
8675
|
+
}
|
|
8676
|
+
});
|
|
8677
|
+
|
|
8678
|
+
// src/lib/memory-queue-client.ts
|
|
8679
|
+
var memory_queue_client_exports = {};
|
|
8680
|
+
__export(memory_queue_client_exports, {
|
|
8681
|
+
batchWriteMemoryViaDaemon: () => batchWriteMemoryViaDaemon,
|
|
8682
|
+
writeMemoryViaDaemon: () => writeMemoryViaDaemon
|
|
8683
|
+
});
|
|
8684
|
+
async function writeMemoryViaDaemon(entry) {
|
|
8685
|
+
if (process.env.EXE_IS_DAEMON === "1") {
|
|
8686
|
+
enqueueMemory(entry);
|
|
8687
|
+
return false;
|
|
8688
|
+
}
|
|
8689
|
+
if (!isClientConnected()) {
|
|
8690
|
+
enqueueMemory(entry);
|
|
8691
|
+
return false;
|
|
8692
|
+
}
|
|
8693
|
+
try {
|
|
8694
|
+
const response = await sendDaemonRequest({
|
|
8695
|
+
type: "write-memory",
|
|
8696
|
+
entry
|
|
8697
|
+
});
|
|
8698
|
+
if (response.ok) return true;
|
|
8699
|
+
enqueueMemory(entry);
|
|
8700
|
+
return false;
|
|
8701
|
+
} catch {
|
|
8702
|
+
enqueueMemory(entry);
|
|
8703
|
+
return false;
|
|
8704
|
+
}
|
|
8705
|
+
}
|
|
8706
|
+
async function batchWriteMemoryViaDaemon(entries) {
|
|
8707
|
+
if (entries.length === 0) return 0;
|
|
8708
|
+
if (process.env.EXE_IS_DAEMON === "1" || !isClientConnected()) {
|
|
8709
|
+
for (const entry of entries) enqueueMemory(entry);
|
|
8710
|
+
return 0;
|
|
8711
|
+
}
|
|
8712
|
+
try {
|
|
8713
|
+
const response = await sendDaemonRequest({
|
|
8714
|
+
type: "batch-write-memory",
|
|
8715
|
+
entries
|
|
8716
|
+
});
|
|
8717
|
+
if (response.ok) return response.count ?? entries.length;
|
|
8718
|
+
for (const entry of entries) enqueueMemory(entry);
|
|
8719
|
+
return 0;
|
|
8720
|
+
} catch {
|
|
8721
|
+
for (const entry of entries) enqueueMemory(entry);
|
|
8722
|
+
return 0;
|
|
8723
|
+
}
|
|
8724
|
+
}
|
|
8725
|
+
var init_memory_queue_client = __esm({
|
|
8726
|
+
"src/lib/memory-queue-client.ts"() {
|
|
8727
|
+
"use strict";
|
|
8728
|
+
init_exe_daemon_client();
|
|
8729
|
+
init_memory_queue();
|
|
8730
|
+
}
|
|
8731
|
+
});
|
|
8732
|
+
|
|
8661
8733
|
// src/lib/active-agent.ts
|
|
8662
8734
|
init_config();
|
|
8663
8735
|
init_session_key();
|
|
@@ -8768,209 +8840,6 @@ function getActiveAgent() {
|
|
|
8768
8840
|
|
|
8769
8841
|
// src/adapters/claude/hooks/pre-compact.ts
|
|
8770
8842
|
init_task_scope();
|
|
8771
|
-
|
|
8772
|
-
// src/lib/auto-checkpoint.ts
|
|
8773
|
-
var FILE_RE = /(?:^|\s)([\w./-]+\.(?:ts|tsx|js|jsx|json|md|yml|yaml|sql|go|py|css|scss|html|sh))(?:\b|$)/g;
|
|
8774
|
-
var DECISION_RE = /\b(decision:|decided:|we decided|founder directive|captured in .*architecture|source of truth)\b/i;
|
|
8775
|
-
function asString(value, fallback = "") {
|
|
8776
|
-
if (value == null) return fallback;
|
|
8777
|
-
return String(value);
|
|
8778
|
-
}
|
|
8779
|
-
function compactLine(text, max = 220) {
|
|
8780
|
-
return text.replace(/\s+/g, " ").trim().slice(0, max);
|
|
8781
|
-
}
|
|
8782
|
-
function topEntries(counts, limit) {
|
|
8783
|
-
return [...counts.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, limit).map(([name, count]) => `${name}(${count})`);
|
|
8784
|
-
}
|
|
8785
|
-
function buildAutoCheckpoint(input2) {
|
|
8786
|
-
const maxSamples = input2.maxSamples ?? 8;
|
|
8787
|
-
const projectCounts = /* @__PURE__ */ new Map();
|
|
8788
|
-
const toolCounts = /* @__PURE__ */ new Map();
|
|
8789
|
-
const files = /* @__PURE__ */ new Set();
|
|
8790
|
-
const errors = [];
|
|
8791
|
-
const samples = [];
|
|
8792
|
-
const decisionTexts = [];
|
|
8793
|
-
for (const row of input2.memories) {
|
|
8794
|
-
const tool = asString(row.tool_name, "unknown");
|
|
8795
|
-
const project = asString(row.project_name, input2.projectName || "unknown");
|
|
8796
|
-
const raw = asString(row.raw_text);
|
|
8797
|
-
const hasError = row.has_error === 1 || row.has_error === true;
|
|
8798
|
-
toolCounts.set(tool, (toolCounts.get(tool) ?? 0) + 1);
|
|
8799
|
-
projectCounts.set(project, (projectCounts.get(project) ?? 0) + 1);
|
|
8800
|
-
if (hasError && errors.length < 5) errors.push(compactLine(raw, 180));
|
|
8801
|
-
if (samples.length < maxSamples && raw.length > 30) {
|
|
8802
|
-
samples.push(`[${tool}] ${compactLine(raw)}`);
|
|
8803
|
-
}
|
|
8804
|
-
if (DECISION_RE.test(raw) && decisionTexts.length < 5) {
|
|
8805
|
-
decisionTexts.push(`AUTO DECISION CANDIDATE [${input2.agentId}]: ${compactLine(raw, 500)}`);
|
|
8806
|
-
}
|
|
8807
|
-
for (const match of raw.matchAll(FILE_RE)) {
|
|
8808
|
-
if (match[1]) files.add(match[1]);
|
|
8809
|
-
if (files.size >= 20) break;
|
|
8810
|
-
}
|
|
8811
|
-
}
|
|
8812
|
-
const taskLines = (input2.tasks ?? []).slice(0, 10).map((task) => {
|
|
8813
|
-
const status = asString(task.status, "unknown");
|
|
8814
|
-
const priority = asString(task.priority, "?").toUpperCase();
|
|
8815
|
-
const title = asString(task.title, "untitled");
|
|
8816
|
-
const taskFile = asString(task.task_file);
|
|
8817
|
-
return `- [${status}/${priority}] ${title}${taskFile ? ` (${taskFile})` : ""}`;
|
|
8818
|
-
});
|
|
8819
|
-
const parts = [
|
|
8820
|
-
`CONTEXT CHECKPOINT [auto:${input2.reason}]`,
|
|
8821
|
-
`Agent: ${input2.agentId} (${input2.agentRole})`,
|
|
8822
|
-
`Session: ${input2.sessionId}`,
|
|
8823
|
-
`Project: ${input2.projectName}`,
|
|
8824
|
-
`Time: ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
8825
|
-
"",
|
|
8826
|
-
"## Recent Activity",
|
|
8827
|
-
`- Memories scanned: ${input2.memories.length}`,
|
|
8828
|
-
`- Projects: ${topEntries(projectCounts, 5).join(", ") || input2.projectName}`,
|
|
8829
|
-
`- Tools: ${topEntries(toolCounts, 8).join(", ") || "none"}`
|
|
8830
|
-
];
|
|
8831
|
-
if (taskLines.length > 0) {
|
|
8832
|
-
parts.push("", "## Open / Active Tasks", ...taskLines);
|
|
8833
|
-
}
|
|
8834
|
-
if (files.size > 0) {
|
|
8835
|
-
parts.push("", "## Files Mentioned", ...[...files].slice(0, 20).map((f) => `- ${f}`));
|
|
8836
|
-
}
|
|
8837
|
-
if (samples.length > 0) {
|
|
8838
|
-
parts.push("", "## Important Recent Traces", ...samples.map((s) => `- ${s}`));
|
|
8839
|
-
}
|
|
8840
|
-
if (errors.length > 0) {
|
|
8841
|
-
parts.push("", "## Errors / Risks", ...errors.map((e) => `- ${e}`));
|
|
8842
|
-
}
|
|
8843
|
-
if (decisionTexts.length > 0) {
|
|
8844
|
-
parts.push("", "## Decision Candidates", ...decisionTexts.map((d) => `- ${d.replace(/^AUTO DECISION CANDIDATE \\[[^\\]]+\\]: /, "")}`));
|
|
8845
|
-
}
|
|
8846
|
-
return {
|
|
8847
|
-
checkpointText: parts.join("\n"),
|
|
8848
|
-
decisionTexts
|
|
8849
|
-
};
|
|
8850
|
-
}
|
|
8851
|
-
|
|
8852
|
-
// src/lib/memory-queue-client.ts
|
|
8853
|
-
init_exe_daemon_client();
|
|
8854
|
-
|
|
8855
|
-
// src/lib/memory-queue.ts
|
|
8856
|
-
init_config();
|
|
8857
|
-
import { appendFileSync as appendFileSync2, readFileSync as readFileSync14, renameSync as renameSync4, unlinkSync as unlinkSync8, existsSync as existsSync16, statSync as statSync2 } from "fs";
|
|
8858
|
-
import path20 from "path";
|
|
8859
|
-
var QUEUE_PATH2 = path20.join(EXE_AI_DIR, "memory-queue.jsonl");
|
|
8860
|
-
var PROCESSING_PATH = QUEUE_PATH2 + ".processing";
|
|
8861
|
-
var TTL_MS2 = 24 * 60 * 60 * 1e3;
|
|
8862
|
-
function enqueueMemory(entry) {
|
|
8863
|
-
appendFileSync2(QUEUE_PATH2, JSON.stringify(entry) + "\n");
|
|
8864
|
-
}
|
|
8865
|
-
|
|
8866
|
-
// src/lib/memory-queue-client.ts
|
|
8867
|
-
async function writeMemoryViaDaemon(entry) {
|
|
8868
|
-
if (process.env.EXE_IS_DAEMON === "1") {
|
|
8869
|
-
enqueueMemory(entry);
|
|
8870
|
-
return false;
|
|
8871
|
-
}
|
|
8872
|
-
if (!isClientConnected()) {
|
|
8873
|
-
enqueueMemory(entry);
|
|
8874
|
-
return false;
|
|
8875
|
-
}
|
|
8876
|
-
try {
|
|
8877
|
-
const response = await sendDaemonRequest({
|
|
8878
|
-
type: "write-memory",
|
|
8879
|
-
entry
|
|
8880
|
-
});
|
|
8881
|
-
if (response.ok) return true;
|
|
8882
|
-
enqueueMemory(entry);
|
|
8883
|
-
return false;
|
|
8884
|
-
} catch {
|
|
8885
|
-
enqueueMemory(entry);
|
|
8886
|
-
return false;
|
|
8887
|
-
}
|
|
8888
|
-
}
|
|
8889
|
-
|
|
8890
|
-
// src/lib/checkpoint-orchestrator.ts
|
|
8891
|
-
function toolNameForReason(reason) {
|
|
8892
|
-
switch (reason) {
|
|
8893
|
-
case "periodic":
|
|
8894
|
-
return "auto-summary";
|
|
8895
|
-
case "session-end":
|
|
8896
|
-
return "SessionEnd";
|
|
8897
|
-
case "pre-compact":
|
|
8898
|
-
return "pre-compact-hook";
|
|
8899
|
-
case "capacity-signal":
|
|
8900
|
-
return "auto-checkpoint";
|
|
8901
|
-
}
|
|
8902
|
-
}
|
|
8903
|
-
function importanceForReason(reason, override) {
|
|
8904
|
-
if (override !== void 0) return override;
|
|
8905
|
-
switch (reason) {
|
|
8906
|
-
case "periodic":
|
|
8907
|
-
return 7;
|
|
8908
|
-
case "session-end":
|
|
8909
|
-
case "pre-compact":
|
|
8910
|
-
case "capacity-signal":
|
|
8911
|
-
return 8;
|
|
8912
|
-
}
|
|
8913
|
-
}
|
|
8914
|
-
function buildContinuityCheckpoint(input2) {
|
|
8915
|
-
const { checkpointText, decisionTexts } = buildAutoCheckpoint({
|
|
8916
|
-
agentId: input2.agentId,
|
|
8917
|
-
agentRole: input2.agentRole,
|
|
8918
|
-
sessionId: input2.sessionId,
|
|
8919
|
-
projectName: input2.projectName,
|
|
8920
|
-
reason: input2.reason,
|
|
8921
|
-
memories: input2.memories ?? [],
|
|
8922
|
-
tasks: input2.tasks ?? [],
|
|
8923
|
-
maxSamples: input2.maxSamples
|
|
8924
|
-
});
|
|
8925
|
-
const extra = input2.extraSections?.filter((section) => section.trim().length > 0) ?? [];
|
|
8926
|
-
return {
|
|
8927
|
-
checkpointText: extra.length > 0 ? `${checkpointText}
|
|
8928
|
-
|
|
8929
|
-
${extra.join("\n\n")}` : checkpointText,
|
|
8930
|
-
decisionTexts
|
|
8931
|
-
};
|
|
8932
|
-
}
|
|
8933
|
-
async function writeContinuityCheckpoint(input2) {
|
|
8934
|
-
const result = buildContinuityCheckpoint(input2);
|
|
8935
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
8936
|
-
await writeMemoryViaDaemon({
|
|
8937
|
-
raw_text: result.checkpointText,
|
|
8938
|
-
agent_id: input2.agentId,
|
|
8939
|
-
agent_role: input2.agentRole,
|
|
8940
|
-
session_id: input2.sessionId,
|
|
8941
|
-
tool_name: toolNameForReason(input2.reason),
|
|
8942
|
-
project_name: input2.projectName,
|
|
8943
|
-
timestamp: now,
|
|
8944
|
-
importance: importanceForReason(input2.reason, input2.importance),
|
|
8945
|
-
task_id: input2.taskId,
|
|
8946
|
-
memory_type: "checkpoint"
|
|
8947
|
-
});
|
|
8948
|
-
const decisionLimit = input2.reason === "periodic" ? 3 : 5;
|
|
8949
|
-
for (const decisionText of result.decisionTexts.slice(0, decisionLimit)) {
|
|
8950
|
-
await writeMemoryViaDaemon({
|
|
8951
|
-
raw_text: decisionText,
|
|
8952
|
-
agent_id: input2.agentId,
|
|
8953
|
-
agent_role: input2.agentRole,
|
|
8954
|
-
session_id: input2.sessionId,
|
|
8955
|
-
tool_name: "auto-decision",
|
|
8956
|
-
project_name: input2.projectName,
|
|
8957
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8958
|
-
importance: 8,
|
|
8959
|
-
memory_type: "decision"
|
|
8960
|
-
});
|
|
8961
|
-
}
|
|
8962
|
-
return result;
|
|
8963
|
-
}
|
|
8964
|
-
async function checkpointActiveTask(input2) {
|
|
8965
|
-
const { writeCheckpoint: writeCheckpoint2 } = await Promise.resolve().then(() => (init_tasks(), tasks_exports));
|
|
8966
|
-
await writeCheckpoint2({
|
|
8967
|
-
taskId: input2.taskId,
|
|
8968
|
-
step: input2.step ?? "pre-compaction-checkpoint",
|
|
8969
|
-
contextSummary: `Auto-checkpoint before context compaction. Task: ${input2.taskTitle}. Session: ${input2.sessionId}. Project: ${input2.projectName}.`
|
|
8970
|
-
});
|
|
8971
|
-
}
|
|
8972
|
-
|
|
8973
|
-
// src/adapters/claude/hooks/pre-compact.ts
|
|
8974
8843
|
if (!process.env.AGENT_ID) {
|
|
8975
8844
|
process.env.AGENT_ID = "default";
|
|
8976
8845
|
process.env.AGENT_ROLE = "employee";
|
|
@@ -9013,11 +8882,11 @@ ${taskLines}`);
|
|
|
9013
8882
|
const taskId = String(task.id);
|
|
9014
8883
|
const taskTitle = String(task.title);
|
|
9015
8884
|
try {
|
|
9016
|
-
await
|
|
8885
|
+
const { writeCheckpoint: writeCheckpoint2 } = await Promise.resolve().then(() => (init_tasks(), tasks_exports));
|
|
8886
|
+
await writeCheckpoint2({
|
|
9017
8887
|
taskId,
|
|
9018
|
-
|
|
9019
|
-
|
|
9020
|
-
projectName
|
|
8888
|
+
step: "pre-compaction-checkpoint",
|
|
8889
|
+
contextSummary: `Auto-checkpoint before context compaction. Task: ${taskTitle}. Session: ${payload.session_id}. Project: ${projectName}.`
|
|
9021
8890
|
});
|
|
9022
8891
|
} catch {
|
|
9023
8892
|
}
|
|
@@ -9040,14 +8909,18 @@ ${taskLines}`);
|
|
|
9040
8909
|
if (lastCheckpoint?.files_touched?.length) {
|
|
9041
8910
|
recoveryLines.push(`Files: ${lastCheckpoint.files_touched.join(", ")}`);
|
|
9042
8911
|
}
|
|
9043
|
-
await
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
|
|
9049
|
-
|
|
9050
|
-
|
|
8912
|
+
const { writeMemoryViaDaemon: writeMemoryViaDaemon2 } = await Promise.resolve().then(() => (init_memory_queue_client(), memory_queue_client_exports));
|
|
8913
|
+
await writeMemoryViaDaemon2({
|
|
8914
|
+
raw_text: recoveryLines.join("\n"),
|
|
8915
|
+
agent_id: agent.agentId,
|
|
8916
|
+
agent_role: agent.agentRole,
|
|
8917
|
+
session_id: payload.session_id,
|
|
8918
|
+
tool_name: "pre-compact-hook",
|
|
8919
|
+
project_name: projectName,
|
|
8920
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8921
|
+
importance: 8,
|
|
8922
|
+
task_id: taskId,
|
|
8923
|
+
memory_type: "checkpoint"
|
|
9051
8924
|
});
|
|
9052
8925
|
} catch {
|
|
9053
8926
|
}
|