@askexenow/exe-os 0.9.61 → 0.9.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deploy/stack-manifests/v0.9.json +62 -13
- package/dist/bin/backfill-conversations.js +210 -2
- package/dist/bin/backfill-responses.js +210 -2
- package/dist/bin/backfill-vectors.js +47 -2
- package/dist/bin/cleanup-stale-review-tasks.js +210 -2
- package/dist/bin/cli.js +488 -25
- package/dist/bin/exe-agent-config.js +2 -2
- package/dist/bin/exe-agent.js +2 -2
- package/dist/bin/exe-assign.js +210 -2
- package/dist/bin/exe-boot.js +47 -2
- package/dist/bin/exe-call.js +2 -2
- package/dist/bin/exe-cloud.js +2 -2
- package/dist/bin/exe-dispatch.js +210 -2
- package/dist/bin/exe-doctor.js +2691 -1212
- package/dist/bin/exe-export-behaviors.js +210 -2
- package/dist/bin/exe-forget.js +264 -2
- package/dist/bin/exe-gateway.js +210 -2
- package/dist/bin/exe-heartbeat.js +212 -4
- package/dist/bin/exe-kill.js +210 -2
- package/dist/bin/exe-launch-agent.js +210 -2
- package/dist/bin/exe-link.js +47 -2
- package/dist/bin/exe-new-employee.js +113 -3
- package/dist/bin/exe-pending-messages.js +210 -2
- package/dist/bin/exe-pending-notifications.js +210 -2
- package/dist/bin/exe-pending-reviews.js +210 -2
- package/dist/bin/exe-rename.js +210 -2
- package/dist/bin/exe-review.js +210 -2
- package/dist/bin/exe-search.js +234 -3
- package/dist/bin/exe-session-cleanup.js +210 -2
- package/dist/bin/exe-settings.js +2 -2
- package/dist/bin/exe-start-codex.js +322 -4
- package/dist/bin/exe-start-opencode.js +336 -4
- package/dist/bin/exe-status.js +210 -2
- package/dist/bin/exe-team.js +210 -2
- package/dist/bin/git-sweep.js +210 -2
- package/dist/bin/graph-backfill.js +210 -2
- package/dist/bin/graph-export.js +210 -2
- package/dist/bin/install.js +113 -3
- package/dist/bin/intercom-check.js +210 -2
- package/dist/bin/scan-tasks.js +210 -2
- package/dist/bin/setup.js +47 -2
- package/dist/bin/shard-migrate.js +210 -2
- package/dist/bin/stack-update.js +158 -13
- package/dist/bin/update.js +2 -2
- package/dist/gateway/index.js +210 -2
- package/dist/hooks/bug-report-worker.js +321 -44
- package/dist/hooks/codex-stop-task-finalizer.js +210 -2
- package/dist/hooks/commit-complete.js +210 -2
- package/dist/hooks/error-recall.js +234 -3
- package/dist/hooks/exe-heartbeat-hook.js +2 -2
- package/dist/hooks/ingest-worker.js +2 -2
- package/dist/hooks/ingest.js +210 -2
- package/dist/hooks/instructions-loaded.js +210 -2
- package/dist/hooks/notification.js +210 -2
- package/dist/hooks/post-compact.js +210 -2
- package/dist/hooks/post-tool-combined.js +234 -3
- package/dist/hooks/pre-compact.js +446 -111
- package/dist/hooks/pre-tool-use.js +210 -2
- package/dist/hooks/prompt-submit.js +234 -3
- package/dist/hooks/session-end.js +347 -124
- package/dist/hooks/session-start.js +236 -5
- package/dist/hooks/stop.js +210 -2
- package/dist/hooks/subagent-stop.js +210 -2
- package/dist/hooks/summary-worker.js +171 -74
- package/dist/index.js +210 -2
- package/dist/lib/agent-config.js +2 -2
- package/dist/lib/cloud-sync.js +47 -2
- package/dist/lib/config.js +2 -2
- package/dist/lib/consolidation.js +2 -2
- package/dist/lib/database.js +47 -2
- package/dist/lib/db-daemon-client.js +2 -2
- package/dist/lib/db.js +47 -2
- package/dist/lib/device-registry.js +47 -2
- package/dist/lib/embedder.js +2 -2
- package/dist/lib/employee-templates.js +2 -2
- package/dist/lib/employees.js +2 -2
- package/dist/lib/exe-daemon-client.js +2 -2
- package/dist/lib/exe-daemon.js +592 -10
- package/dist/lib/hybrid-search.js +234 -3
- package/dist/lib/identity.js +2 -2
- package/dist/lib/license.js +2 -2
- package/dist/lib/messaging.js +2 -2
- package/dist/lib/reminders.js +2 -2
- package/dist/lib/schedules.js +47 -2
- package/dist/lib/skill-learning.js +2 -2
- package/dist/lib/store.js +210 -2
- package/dist/lib/task-router.js +2 -2
- package/dist/lib/tasks.js +2 -2
- package/dist/lib/tmux-routing.js +2 -2
- package/dist/lib/token-spend.js +2 -2
- package/dist/mcp/server.js +608 -10
- package/dist/mcp/tools/complete-reminder.js +2 -2
- package/dist/mcp/tools/create-reminder.js +2 -2
- package/dist/mcp/tools/create-task.js +2 -2
- package/dist/mcp/tools/deactivate-behavior.js +2 -2
- package/dist/mcp/tools/list-reminders.js +2 -2
- package/dist/mcp/tools/list-tasks.js +2 -2
- package/dist/mcp/tools/send-message.js +2 -2
- package/dist/mcp/tools/update-task.js +2 -2
- package/dist/runtime/index.js +210 -2
- package/dist/tui/App.js +210 -2
- package/package.json +3 -2
- package/stack.release.json +23 -7
|
@@ -257,8 +257,8 @@ var init_config = __esm({
|
|
|
257
257
|
rerankerAutoTrigger: {
|
|
258
258
|
enabled: true,
|
|
259
259
|
broadQueryMinCardinality: 5e4,
|
|
260
|
-
fetchTopK:
|
|
261
|
-
returnTopK:
|
|
260
|
+
fetchTopK: 200,
|
|
261
|
+
returnTopK: 20
|
|
262
262
|
}
|
|
263
263
|
},
|
|
264
264
|
graphRagEnabled: true,
|
|
@@ -3299,6 +3299,51 @@ async function ensureSchema() {
|
|
|
3299
3299
|
VALUES (new.rowid, new.content_text, new.sender_name, new.agent_response);
|
|
3300
3300
|
END;
|
|
3301
3301
|
`);
|
|
3302
|
+
await client.executeMultiple(`
|
|
3303
|
+
CREATE TABLE IF NOT EXISTS memory_cards (
|
|
3304
|
+
id TEXT PRIMARY KEY,
|
|
3305
|
+
memory_id TEXT NOT NULL,
|
|
3306
|
+
agent_id TEXT NOT NULL,
|
|
3307
|
+
session_id TEXT NOT NULL,
|
|
3308
|
+
project_name TEXT,
|
|
3309
|
+
timestamp TEXT NOT NULL,
|
|
3310
|
+
card_type TEXT NOT NULL,
|
|
3311
|
+
subject TEXT,
|
|
3312
|
+
predicate TEXT,
|
|
3313
|
+
object TEXT,
|
|
3314
|
+
content TEXT NOT NULL,
|
|
3315
|
+
source_ref TEXT,
|
|
3316
|
+
confidence REAL DEFAULT 0.6,
|
|
3317
|
+
active INTEGER DEFAULT 1,
|
|
3318
|
+
created_at TEXT NOT NULL
|
|
3319
|
+
);
|
|
3320
|
+
|
|
3321
|
+
CREATE INDEX IF NOT EXISTS idx_memory_cards_agent
|
|
3322
|
+
ON memory_cards(agent_id, active, timestamp);
|
|
3323
|
+
|
|
3324
|
+
CREATE INDEX IF NOT EXISTS idx_memory_cards_memory
|
|
3325
|
+
ON memory_cards(memory_id);
|
|
3326
|
+
|
|
3327
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memory_cards_fts
|
|
3328
|
+
USING fts5(content, subject, predicate, object, content='memory_cards', content_rowid='rowid');
|
|
3329
|
+
|
|
3330
|
+
CREATE TRIGGER IF NOT EXISTS memory_cards_fts_ai AFTER INSERT ON memory_cards BEGIN
|
|
3331
|
+
INSERT INTO memory_cards_fts(rowid, content, subject, predicate, object)
|
|
3332
|
+
VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
|
|
3333
|
+
END;
|
|
3334
|
+
|
|
3335
|
+
CREATE TRIGGER IF NOT EXISTS memory_cards_fts_ad AFTER DELETE ON memory_cards BEGIN
|
|
3336
|
+
INSERT INTO memory_cards_fts(memory_cards_fts, rowid, content, subject, predicate, object)
|
|
3337
|
+
VALUES('delete', old.rowid, old.content, old.subject, old.predicate, old.object);
|
|
3338
|
+
END;
|
|
3339
|
+
|
|
3340
|
+
CREATE TRIGGER IF NOT EXISTS memory_cards_fts_au AFTER UPDATE ON memory_cards BEGIN
|
|
3341
|
+
INSERT INTO memory_cards_fts(memory_cards_fts, rowid, content, subject, predicate, object)
|
|
3342
|
+
VALUES('delete', old.rowid, old.content, old.subject, old.predicate, old.object);
|
|
3343
|
+
INSERT INTO memory_cards_fts(rowid, content, subject, predicate, object)
|
|
3344
|
+
VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
|
|
3345
|
+
END;
|
|
3346
|
+
`);
|
|
3302
3347
|
try {
|
|
3303
3348
|
await client.execute({
|
|
3304
3349
|
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
@@ -6680,15 +6725,15 @@ var init_task_scope = __esm({
|
|
|
6680
6725
|
|
|
6681
6726
|
// src/lib/keychain.ts
|
|
6682
6727
|
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
6683
|
-
import { existsSync as
|
|
6728
|
+
import { existsSync as existsSync17 } from "fs";
|
|
6684
6729
|
import { execSync as execSync8 } from "child_process";
|
|
6685
|
-
import
|
|
6730
|
+
import path21 from "path";
|
|
6686
6731
|
import os12 from "os";
|
|
6687
6732
|
function getKeyDir() {
|
|
6688
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ??
|
|
6733
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path21.join(os12.homedir(), ".exe-os");
|
|
6689
6734
|
}
|
|
6690
6735
|
function getKeyPath() {
|
|
6691
|
-
return
|
|
6736
|
+
return path21.join(getKeyDir(), "master.key");
|
|
6692
6737
|
}
|
|
6693
6738
|
function macKeychainGet() {
|
|
6694
6739
|
if (process.platform !== "darwin") return null;
|
|
@@ -6836,7 +6881,7 @@ async function getMasterKey() {
|
|
|
6836
6881
|
}
|
|
6837
6882
|
}
|
|
6838
6883
|
const keyPath = getKeyPath();
|
|
6839
|
-
if (!
|
|
6884
|
+
if (!existsSync17(keyPath)) {
|
|
6840
6885
|
process.stderr.write(
|
|
6841
6886
|
`[keychain] Key not found at ${keyPath} (HOME=${os12.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
6842
6887
|
`
|
|
@@ -7110,12 +7155,12 @@ __export(shard_manager_exports, {
|
|
|
7110
7155
|
listShards: () => listShards,
|
|
7111
7156
|
shardExists: () => shardExists
|
|
7112
7157
|
});
|
|
7113
|
-
import
|
|
7114
|
-
import { existsSync as
|
|
7158
|
+
import path22 from "path";
|
|
7159
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync9, readdirSync as readdirSync5, renameSync as renameSync5, statSync as statSync3 } from "fs";
|
|
7115
7160
|
import { createClient as createClient2 } from "@libsql/client";
|
|
7116
7161
|
function initShardManager(encryptionKey) {
|
|
7117
7162
|
_encryptionKey = encryptionKey;
|
|
7118
|
-
if (!
|
|
7163
|
+
if (!existsSync18(SHARDS_DIR)) {
|
|
7119
7164
|
mkdirSync9(SHARDS_DIR, { recursive: true });
|
|
7120
7165
|
}
|
|
7121
7166
|
_shardingEnabled = true;
|
|
@@ -7145,7 +7190,7 @@ function getShardClient(projectName) {
|
|
|
7145
7190
|
while (_shards.size >= MAX_OPEN_SHARDS) {
|
|
7146
7191
|
evictLRU();
|
|
7147
7192
|
}
|
|
7148
|
-
const dbPath =
|
|
7193
|
+
const dbPath = path22.join(SHARDS_DIR, `${safeName}.db`);
|
|
7149
7194
|
const client = createClient2({
|
|
7150
7195
|
url: `file:${dbPath}`,
|
|
7151
7196
|
encryptionKey: _encryptionKey
|
|
@@ -7156,13 +7201,13 @@ function getShardClient(projectName) {
|
|
|
7156
7201
|
}
|
|
7157
7202
|
function shardExists(projectName) {
|
|
7158
7203
|
const safeName = safeShardName(projectName);
|
|
7159
|
-
return
|
|
7204
|
+
return existsSync18(path22.join(SHARDS_DIR, `${safeName}.db`));
|
|
7160
7205
|
}
|
|
7161
7206
|
function safeShardName(projectName) {
|
|
7162
7207
|
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7163
7208
|
}
|
|
7164
7209
|
function listShards() {
|
|
7165
|
-
if (!
|
|
7210
|
+
if (!existsSync18(SHARDS_DIR)) return [];
|
|
7166
7211
|
return readdirSync5(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
7167
7212
|
}
|
|
7168
7213
|
async function auditShardHealth(options = {}) {
|
|
@@ -7174,8 +7219,8 @@ async function auditShardHealth(options = {}) {
|
|
|
7174
7219
|
const names = listShards();
|
|
7175
7220
|
const shards = [];
|
|
7176
7221
|
for (const name of names) {
|
|
7177
|
-
const dbPath =
|
|
7178
|
-
const stat =
|
|
7222
|
+
const dbPath = path22.join(SHARDS_DIR, `${name}.db`);
|
|
7223
|
+
const stat = statSync3(dbPath);
|
|
7179
7224
|
const item = {
|
|
7180
7225
|
name,
|
|
7181
7226
|
path: dbPath,
|
|
@@ -7209,8 +7254,8 @@ async function auditShardHealth(options = {}) {
|
|
|
7209
7254
|
_shards.delete(name);
|
|
7210
7255
|
_shardLastAccess.delete(name);
|
|
7211
7256
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7212
|
-
const archivedPath =
|
|
7213
|
-
|
|
7257
|
+
const archivedPath = path22.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
|
|
7258
|
+
renameSync5(dbPath, archivedPath);
|
|
7214
7259
|
item.archivedPath = archivedPath;
|
|
7215
7260
|
}
|
|
7216
7261
|
} finally {
|
|
@@ -7426,12 +7471,12 @@ async function getReadyShardClient(projectName) {
|
|
|
7426
7471
|
client.close();
|
|
7427
7472
|
_shards.delete(safeName);
|
|
7428
7473
|
_shardLastAccess.delete(safeName);
|
|
7429
|
-
const dbPath =
|
|
7430
|
-
if (
|
|
7431
|
-
const stat =
|
|
7474
|
+
const dbPath = path22.join(SHARDS_DIR, `${safeName}.db`);
|
|
7475
|
+
if (existsSync18(dbPath)) {
|
|
7476
|
+
const stat = statSync3(dbPath);
|
|
7432
7477
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7433
|
-
const archivedPath =
|
|
7434
|
-
|
|
7478
|
+
const archivedPath = path22.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
7479
|
+
renameSync5(dbPath, archivedPath);
|
|
7435
7480
|
process.stderr.write(
|
|
7436
7481
|
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
|
|
7437
7482
|
`
|
|
@@ -7498,7 +7543,7 @@ var init_shard_manager = __esm({
|
|
|
7498
7543
|
"src/lib/shard-manager.ts"() {
|
|
7499
7544
|
"use strict";
|
|
7500
7545
|
init_config();
|
|
7501
|
-
SHARDS_DIR =
|
|
7546
|
+
SHARDS_DIR = path22.join(EXE_AI_DIR, "shards");
|
|
7502
7547
|
SHARD_IDLE_MS = 5 * 60 * 1e3;
|
|
7503
7548
|
MAX_OPEN_SHARDS = 10;
|
|
7504
7549
|
EVICTION_INTERVAL_MS = 60 * 1e3;
|
|
@@ -7765,6 +7810,164 @@ ${p.content}`).join("\n\n");
|
|
|
7765
7810
|
}
|
|
7766
7811
|
});
|
|
7767
7812
|
|
|
7813
|
+
// src/lib/memory-cards.ts
|
|
7814
|
+
var memory_cards_exports = {};
|
|
7815
|
+
__export(memory_cards_exports, {
|
|
7816
|
+
extractMemoryCards: () => extractMemoryCards,
|
|
7817
|
+
insertMemoryCardsForBatch: () => insertMemoryCardsForBatch,
|
|
7818
|
+
searchMemoryCards: () => searchMemoryCards
|
|
7819
|
+
});
|
|
7820
|
+
import { createHash as createHash2 } from "crypto";
|
|
7821
|
+
function stableId(memoryId, type, content) {
|
|
7822
|
+
return createHash2("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
|
|
7823
|
+
}
|
|
7824
|
+
function cleanText(text) {
|
|
7825
|
+
return text.replace(/```[\s\S]*?```/g, " ").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
7826
|
+
}
|
|
7827
|
+
function splitSentences(text) {
|
|
7828
|
+
return cleanText(text).split(/(?<=[.!?])\s+|\n+/).map((s) => s.trim()).filter((s) => s.length >= 24 && s.length <= MAX_SENTENCE_CHARS);
|
|
7829
|
+
}
|
|
7830
|
+
function inferCardType(sentence, toolName) {
|
|
7831
|
+
const lower = sentence.toLowerCase();
|
|
7832
|
+
if (toolName === "store_decision" || /\b(decided|decision|adr|approved|rejected)\b/.test(lower)) return "decision";
|
|
7833
|
+
if (/\b(prefers|preference|likes|dislikes|wants|doesn't want|does not want)\b/.test(lower)) return "preference";
|
|
7834
|
+
if (/\b(changed|updated|replaced|now|no longer|instead|supersedes)\b/.test(lower)) return "belief_update";
|
|
7835
|
+
if (toolName && ["Read", "Write", "Edit", "Bash"].includes(toolName)) return "code";
|
|
7836
|
+
if (/\b(meeting|deadline|shipped|launched|completed|failed|blocked|assigned|created)\b/.test(lower)) return "event";
|
|
7837
|
+
return "fact";
|
|
7838
|
+
}
|
|
7839
|
+
function extractSubject(sentence, agentId) {
|
|
7840
|
+
const explicit = sentence.match(/\b([A-Z][a-zA-Z0-9_-]{2,}(?:\s+[A-Z][a-zA-Z0-9_-]{2,})?)\b/);
|
|
7841
|
+
return explicit?.[1] ?? agentId;
|
|
7842
|
+
}
|
|
7843
|
+
function predicateFor(type) {
|
|
7844
|
+
switch (type) {
|
|
7845
|
+
case "preference":
|
|
7846
|
+
return "prefers";
|
|
7847
|
+
case "belief_update":
|
|
7848
|
+
return "updated";
|
|
7849
|
+
case "decision":
|
|
7850
|
+
return "decided";
|
|
7851
|
+
case "event":
|
|
7852
|
+
return "happened";
|
|
7853
|
+
case "code":
|
|
7854
|
+
return "implemented";
|
|
7855
|
+
default:
|
|
7856
|
+
return "states";
|
|
7857
|
+
}
|
|
7858
|
+
}
|
|
7859
|
+
function extractMemoryCards(row) {
|
|
7860
|
+
const sentences = splitSentences(row.raw_text);
|
|
7861
|
+
const cards = [];
|
|
7862
|
+
for (const sentence of sentences) {
|
|
7863
|
+
const type = inferCardType(sentence, row.tool_name);
|
|
7864
|
+
const subject = extractSubject(sentence, row.agent_id);
|
|
7865
|
+
const content = sentence.length > MAX_SENTENCE_CHARS ? `${sentence.slice(0, MAX_SENTENCE_CHARS - 1)}\u2026` : sentence;
|
|
7866
|
+
cards.push({
|
|
7867
|
+
id: stableId(row.id, type, content),
|
|
7868
|
+
memory_id: row.id,
|
|
7869
|
+
agent_id: row.agent_id,
|
|
7870
|
+
session_id: row.session_id,
|
|
7871
|
+
project_name: row.project_name ?? null,
|
|
7872
|
+
timestamp: row.timestamp,
|
|
7873
|
+
card_type: type,
|
|
7874
|
+
subject,
|
|
7875
|
+
predicate: predicateFor(type),
|
|
7876
|
+
object: content,
|
|
7877
|
+
content,
|
|
7878
|
+
source_ref: row.id,
|
|
7879
|
+
confidence: type === "fact" ? 0.55 : 0.65
|
|
7880
|
+
});
|
|
7881
|
+
if (cards.length >= MAX_CARDS_PER_MEMORY) break;
|
|
7882
|
+
}
|
|
7883
|
+
return cards;
|
|
7884
|
+
}
|
|
7885
|
+
async function insertMemoryCardsForBatch(rows) {
|
|
7886
|
+
const cards = rows.flatMap(extractMemoryCards);
|
|
7887
|
+
if (cards.length === 0) return 0;
|
|
7888
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
7889
|
+
const client = getClient();
|
|
7890
|
+
const stmts = cards.map((card) => ({
|
|
7891
|
+
sql: `INSERT OR IGNORE INTO memory_cards
|
|
7892
|
+
(id, memory_id, agent_id, session_id, project_name, timestamp, card_type,
|
|
7893
|
+
subject, predicate, object, content, source_ref, confidence, active, created_at)
|
|
7894
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?)`,
|
|
7895
|
+
args: [
|
|
7896
|
+
card.id,
|
|
7897
|
+
card.memory_id,
|
|
7898
|
+
card.agent_id,
|
|
7899
|
+
card.session_id,
|
|
7900
|
+
card.project_name,
|
|
7901
|
+
card.timestamp,
|
|
7902
|
+
card.card_type,
|
|
7903
|
+
card.subject,
|
|
7904
|
+
card.predicate,
|
|
7905
|
+
card.object,
|
|
7906
|
+
card.content,
|
|
7907
|
+
card.source_ref,
|
|
7908
|
+
card.confidence,
|
|
7909
|
+
now
|
|
7910
|
+
]
|
|
7911
|
+
}));
|
|
7912
|
+
await client.batch(stmts, "write");
|
|
7913
|
+
return cards.length;
|
|
7914
|
+
}
|
|
7915
|
+
function buildMatchExpr(queryText) {
|
|
7916
|
+
const terms = queryText.toLowerCase().split(/\s+/).filter((t) => t.length >= 3).map((t) => t.replace(/[^a-z0-9_]/g, "")).filter((t) => t.length >= 3).slice(0, 12);
|
|
7917
|
+
if (terms.length === 0) return null;
|
|
7918
|
+
return terms.map((t) => `${t}*`).join(terms.length >= 3 ? " AND " : " OR ");
|
|
7919
|
+
}
|
|
7920
|
+
async function searchMemoryCards(queryText, agentId, options) {
|
|
7921
|
+
const limit = options?.limit ?? 10;
|
|
7922
|
+
const matchExpr = buildMatchExpr(queryText);
|
|
7923
|
+
if (!matchExpr) return [];
|
|
7924
|
+
let sql = `SELECT c.id, c.memory_id, c.agent_id, c.session_id, c.project_name,
|
|
7925
|
+
c.timestamp, c.card_type, c.content, c.source_ref, c.confidence
|
|
7926
|
+
FROM memory_cards c
|
|
7927
|
+
JOIN memory_cards_fts fts ON c.rowid = fts.rowid
|
|
7928
|
+
WHERE memory_cards_fts MATCH ?
|
|
7929
|
+
AND c.agent_id = ?
|
|
7930
|
+
AND COALESCE(c.active, 1) = 1`;
|
|
7931
|
+
const args = [matchExpr, agentId];
|
|
7932
|
+
if (options?.projectName) {
|
|
7933
|
+
sql += ` AND c.project_name = ?`;
|
|
7934
|
+
args.push(options.projectName);
|
|
7935
|
+
}
|
|
7936
|
+
if (options?.since) {
|
|
7937
|
+
sql += ` AND c.timestamp >= ?`;
|
|
7938
|
+
args.push(options.since);
|
|
7939
|
+
}
|
|
7940
|
+
sql += ` ORDER BY rank LIMIT ?`;
|
|
7941
|
+
args.push(limit);
|
|
7942
|
+
const result = await getClient().execute({ sql, args });
|
|
7943
|
+
return result.rows.map((row) => ({
|
|
7944
|
+
id: `card:${String(row.id)}`,
|
|
7945
|
+
agent_id: String(row.agent_id),
|
|
7946
|
+
agent_role: "memory_card",
|
|
7947
|
+
session_id: String(row.session_id),
|
|
7948
|
+
timestamp: String(row.timestamp),
|
|
7949
|
+
tool_name: `memory_card:${String(row.card_type)}`,
|
|
7950
|
+
project_name: row.project_name == null ? "" : String(row.project_name),
|
|
7951
|
+
has_error: false,
|
|
7952
|
+
raw_text: `[${String(row.card_type)}] ${String(row.content)}
|
|
7953
|
+
Source memory: ${String(row.source_ref ?? row.memory_id)}`,
|
|
7954
|
+
vector: [],
|
|
7955
|
+
importance: 6,
|
|
7956
|
+
status: "active",
|
|
7957
|
+
confidence: Number(row.confidence ?? 0.6),
|
|
7958
|
+
last_accessed: String(row.timestamp)
|
|
7959
|
+
}));
|
|
7960
|
+
}
|
|
7961
|
+
var MAX_CARDS_PER_MEMORY, MAX_SENTENCE_CHARS;
|
|
7962
|
+
var init_memory_cards = __esm({
|
|
7963
|
+
"src/lib/memory-cards.ts"() {
|
|
7964
|
+
"use strict";
|
|
7965
|
+
init_database();
|
|
7966
|
+
MAX_CARDS_PER_MEMORY = 6;
|
|
7967
|
+
MAX_SENTENCE_CHARS = 360;
|
|
7968
|
+
}
|
|
7969
|
+
});
|
|
7970
|
+
|
|
7768
7971
|
// src/lib/store.ts
|
|
7769
7972
|
var store_exports = {};
|
|
7770
7973
|
__export(store_exports, {
|
|
@@ -8103,6 +8306,11 @@ async function flushBatch() {
|
|
|
8103
8306
|
const globalClient = getClient();
|
|
8104
8307
|
const globalStmts = batch.map(buildStmt);
|
|
8105
8308
|
await globalClient.batch(globalStmts, "write");
|
|
8309
|
+
try {
|
|
8310
|
+
const { insertMemoryCardsForBatch: insertMemoryCardsForBatch2 } = await Promise.resolve().then(() => (init_memory_cards(), memory_cards_exports));
|
|
8311
|
+
await insertMemoryCardsForBatch2(batch);
|
|
8312
|
+
} catch {
|
|
8313
|
+
}
|
|
8106
8314
|
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
8107
8315
|
_pendingRecords.splice(0, batch.length);
|
|
8108
8316
|
try {
|
|
@@ -8450,78 +8658,6 @@ var init_fast_db_init = __esm({
|
|
|
8450
8658
|
}
|
|
8451
8659
|
});
|
|
8452
8660
|
|
|
8453
|
-
// src/lib/memory-queue.ts
|
|
8454
|
-
import { appendFileSync as appendFileSync2, readFileSync as readFileSync14, renameSync as renameSync5, unlinkSync as unlinkSync8, existsSync as existsSync18, statSync as statSync3 } from "fs";
|
|
8455
|
-
import path22 from "path";
|
|
8456
|
-
function enqueueMemory(entry) {
|
|
8457
|
-
appendFileSync2(QUEUE_PATH2, JSON.stringify(entry) + "\n");
|
|
8458
|
-
}
|
|
8459
|
-
var QUEUE_PATH2, PROCESSING_PATH, TTL_MS2;
|
|
8460
|
-
var init_memory_queue = __esm({
|
|
8461
|
-
"src/lib/memory-queue.ts"() {
|
|
8462
|
-
"use strict";
|
|
8463
|
-
init_config();
|
|
8464
|
-
QUEUE_PATH2 = path22.join(EXE_AI_DIR, "memory-queue.jsonl");
|
|
8465
|
-
PROCESSING_PATH = QUEUE_PATH2 + ".processing";
|
|
8466
|
-
TTL_MS2 = 24 * 60 * 60 * 1e3;
|
|
8467
|
-
}
|
|
8468
|
-
});
|
|
8469
|
-
|
|
8470
|
-
// src/lib/memory-queue-client.ts
|
|
8471
|
-
var memory_queue_client_exports = {};
|
|
8472
|
-
__export(memory_queue_client_exports, {
|
|
8473
|
-
batchWriteMemoryViaDaemon: () => batchWriteMemoryViaDaemon,
|
|
8474
|
-
writeMemoryViaDaemon: () => writeMemoryViaDaemon
|
|
8475
|
-
});
|
|
8476
|
-
async function writeMemoryViaDaemon(entry) {
|
|
8477
|
-
if (process.env.EXE_IS_DAEMON === "1") {
|
|
8478
|
-
enqueueMemory(entry);
|
|
8479
|
-
return false;
|
|
8480
|
-
}
|
|
8481
|
-
if (!isClientConnected()) {
|
|
8482
|
-
enqueueMemory(entry);
|
|
8483
|
-
return false;
|
|
8484
|
-
}
|
|
8485
|
-
try {
|
|
8486
|
-
const response = await sendDaemonRequest({
|
|
8487
|
-
type: "write-memory",
|
|
8488
|
-
entry
|
|
8489
|
-
});
|
|
8490
|
-
if (response.ok) return true;
|
|
8491
|
-
enqueueMemory(entry);
|
|
8492
|
-
return false;
|
|
8493
|
-
} catch {
|
|
8494
|
-
enqueueMemory(entry);
|
|
8495
|
-
return false;
|
|
8496
|
-
}
|
|
8497
|
-
}
|
|
8498
|
-
async function batchWriteMemoryViaDaemon(entries) {
|
|
8499
|
-
if (entries.length === 0) return 0;
|
|
8500
|
-
if (process.env.EXE_IS_DAEMON === "1" || !isClientConnected()) {
|
|
8501
|
-
for (const entry of entries) enqueueMemory(entry);
|
|
8502
|
-
return 0;
|
|
8503
|
-
}
|
|
8504
|
-
try {
|
|
8505
|
-
const response = await sendDaemonRequest({
|
|
8506
|
-
type: "batch-write-memory",
|
|
8507
|
-
entries
|
|
8508
|
-
});
|
|
8509
|
-
if (response.ok) return response.count ?? entries.length;
|
|
8510
|
-
for (const entry of entries) enqueueMemory(entry);
|
|
8511
|
-
return 0;
|
|
8512
|
-
} catch {
|
|
8513
|
-
for (const entry of entries) enqueueMemory(entry);
|
|
8514
|
-
return 0;
|
|
8515
|
-
}
|
|
8516
|
-
}
|
|
8517
|
-
var init_memory_queue_client = __esm({
|
|
8518
|
-
"src/lib/memory-queue-client.ts"() {
|
|
8519
|
-
"use strict";
|
|
8520
|
-
init_exe_daemon_client();
|
|
8521
|
-
init_memory_queue();
|
|
8522
|
-
}
|
|
8523
|
-
});
|
|
8524
|
-
|
|
8525
8661
|
// src/lib/active-agent.ts
|
|
8526
8662
|
init_config();
|
|
8527
8663
|
init_session_key();
|
|
@@ -8632,6 +8768,209 @@ function getActiveAgent() {
|
|
|
8632
8768
|
|
|
8633
8769
|
// src/adapters/claude/hooks/pre-compact.ts
|
|
8634
8770
|
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
|
|
8635
8974
|
if (!process.env.AGENT_ID) {
|
|
8636
8975
|
process.env.AGENT_ID = "default";
|
|
8637
8976
|
process.env.AGENT_ROLE = "employee";
|
|
@@ -8674,11 +9013,11 @@ ${taskLines}`);
|
|
|
8674
9013
|
const taskId = String(task.id);
|
|
8675
9014
|
const taskTitle = String(task.title);
|
|
8676
9015
|
try {
|
|
8677
|
-
|
|
8678
|
-
await writeCheckpoint2({
|
|
9016
|
+
await checkpointActiveTask({
|
|
8679
9017
|
taskId,
|
|
8680
|
-
|
|
8681
|
-
|
|
9018
|
+
taskTitle,
|
|
9019
|
+
sessionId: payload.session_id,
|
|
9020
|
+
projectName
|
|
8682
9021
|
});
|
|
8683
9022
|
} catch {
|
|
8684
9023
|
}
|
|
@@ -8701,18 +9040,14 @@ ${taskLines}`);
|
|
|
8701
9040
|
if (lastCheckpoint?.files_touched?.length) {
|
|
8702
9041
|
recoveryLines.push(`Files: ${lastCheckpoint.files_touched.join(", ")}`);
|
|
8703
9042
|
}
|
|
8704
|
-
|
|
8705
|
-
|
|
8706
|
-
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
|
|
8711
|
-
|
|
8712
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8713
|
-
importance: 8,
|
|
8714
|
-
task_id: taskId,
|
|
8715
|
-
memory_type: "checkpoint"
|
|
9043
|
+
await writeContinuityCheckpoint({
|
|
9044
|
+
agentId: agent.agentId,
|
|
9045
|
+
agentRole: agent.agentRole,
|
|
9046
|
+
sessionId: payload.session_id,
|
|
9047
|
+
projectName,
|
|
9048
|
+
reason: "pre-compact",
|
|
9049
|
+
taskId,
|
|
9050
|
+
extraSections: [recoveryLines.join("\n")]
|
|
8716
9051
|
});
|
|
8717
9052
|
} catch {
|
|
8718
9053
|
}
|