@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,
|
|
@@ -3302,6 +3302,51 @@ async function ensureSchema() {
|
|
|
3302
3302
|
VALUES (new.rowid, new.content_text, new.sender_name, new.agent_response);
|
|
3303
3303
|
END;
|
|
3304
3304
|
`);
|
|
3305
|
+
await client.executeMultiple(`
|
|
3306
|
+
CREATE TABLE IF NOT EXISTS memory_cards (
|
|
3307
|
+
id TEXT PRIMARY KEY,
|
|
3308
|
+
memory_id TEXT NOT NULL,
|
|
3309
|
+
agent_id TEXT NOT NULL,
|
|
3310
|
+
session_id TEXT NOT NULL,
|
|
3311
|
+
project_name TEXT,
|
|
3312
|
+
timestamp TEXT NOT NULL,
|
|
3313
|
+
card_type TEXT NOT NULL,
|
|
3314
|
+
subject TEXT,
|
|
3315
|
+
predicate TEXT,
|
|
3316
|
+
object TEXT,
|
|
3317
|
+
content TEXT NOT NULL,
|
|
3318
|
+
source_ref TEXT,
|
|
3319
|
+
confidence REAL DEFAULT 0.6,
|
|
3320
|
+
active INTEGER DEFAULT 1,
|
|
3321
|
+
created_at TEXT NOT NULL
|
|
3322
|
+
);
|
|
3323
|
+
|
|
3324
|
+
CREATE INDEX IF NOT EXISTS idx_memory_cards_agent
|
|
3325
|
+
ON memory_cards(agent_id, active, timestamp);
|
|
3326
|
+
|
|
3327
|
+
CREATE INDEX IF NOT EXISTS idx_memory_cards_memory
|
|
3328
|
+
ON memory_cards(memory_id);
|
|
3329
|
+
|
|
3330
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memory_cards_fts
|
|
3331
|
+
USING fts5(content, subject, predicate, object, content='memory_cards', content_rowid='rowid');
|
|
3332
|
+
|
|
3333
|
+
CREATE TRIGGER IF NOT EXISTS memory_cards_fts_ai AFTER INSERT ON memory_cards BEGIN
|
|
3334
|
+
INSERT INTO memory_cards_fts(rowid, content, subject, predicate, object)
|
|
3335
|
+
VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
|
|
3336
|
+
END;
|
|
3337
|
+
|
|
3338
|
+
CREATE TRIGGER IF NOT EXISTS memory_cards_fts_ad AFTER DELETE ON memory_cards BEGIN
|
|
3339
|
+
INSERT INTO memory_cards_fts(memory_cards_fts, rowid, content, subject, predicate, object)
|
|
3340
|
+
VALUES('delete', old.rowid, old.content, old.subject, old.predicate, old.object);
|
|
3341
|
+
END;
|
|
3342
|
+
|
|
3343
|
+
CREATE TRIGGER IF NOT EXISTS memory_cards_fts_au AFTER UPDATE ON memory_cards BEGIN
|
|
3344
|
+
INSERT INTO memory_cards_fts(memory_cards_fts, rowid, content, subject, predicate, object)
|
|
3345
|
+
VALUES('delete', old.rowid, old.content, old.subject, old.predicate, old.object);
|
|
3346
|
+
INSERT INTO memory_cards_fts(rowid, content, subject, predicate, object)
|
|
3347
|
+
VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
|
|
3348
|
+
END;
|
|
3349
|
+
`);
|
|
3305
3350
|
try {
|
|
3306
3351
|
await client.execute({
|
|
3307
3352
|
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
@@ -6889,15 +6934,15 @@ var init_task_scope = __esm({
|
|
|
6889
6934
|
|
|
6890
6935
|
// src/lib/keychain.ts
|
|
6891
6936
|
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
6892
|
-
import { existsSync as
|
|
6937
|
+
import { existsSync as existsSync18 } from "fs";
|
|
6893
6938
|
import { execSync as execSync8 } from "child_process";
|
|
6894
|
-
import
|
|
6939
|
+
import path22 from "path";
|
|
6895
6940
|
import os13 from "os";
|
|
6896
6941
|
function getKeyDir() {
|
|
6897
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ??
|
|
6942
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path22.join(os13.homedir(), ".exe-os");
|
|
6898
6943
|
}
|
|
6899
6944
|
function getKeyPath() {
|
|
6900
|
-
return
|
|
6945
|
+
return path22.join(getKeyDir(), "master.key");
|
|
6901
6946
|
}
|
|
6902
6947
|
function macKeychainGet() {
|
|
6903
6948
|
if (process.platform !== "darwin") return null;
|
|
@@ -7045,7 +7090,7 @@ async function getMasterKey() {
|
|
|
7045
7090
|
}
|
|
7046
7091
|
}
|
|
7047
7092
|
const keyPath = getKeyPath();
|
|
7048
|
-
if (!
|
|
7093
|
+
if (!existsSync18(keyPath)) {
|
|
7049
7094
|
process.stderr.write(
|
|
7050
7095
|
`[keychain] Key not found at ${keyPath} (HOME=${os13.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
7051
7096
|
`
|
|
@@ -7319,12 +7364,12 @@ __export(shard_manager_exports, {
|
|
|
7319
7364
|
listShards: () => listShards,
|
|
7320
7365
|
shardExists: () => shardExists
|
|
7321
7366
|
});
|
|
7322
|
-
import
|
|
7323
|
-
import { existsSync as
|
|
7367
|
+
import path23 from "path";
|
|
7368
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync10, readdirSync as readdirSync5, renameSync as renameSync5, statSync as statSync3 } from "fs";
|
|
7324
7369
|
import { createClient as createClient2 } from "@libsql/client";
|
|
7325
7370
|
function initShardManager(encryptionKey) {
|
|
7326
7371
|
_encryptionKey = encryptionKey;
|
|
7327
|
-
if (!
|
|
7372
|
+
if (!existsSync19(SHARDS_DIR)) {
|
|
7328
7373
|
mkdirSync10(SHARDS_DIR, { recursive: true });
|
|
7329
7374
|
}
|
|
7330
7375
|
_shardingEnabled = true;
|
|
@@ -7354,7 +7399,7 @@ function getShardClient(projectName) {
|
|
|
7354
7399
|
while (_shards.size >= MAX_OPEN_SHARDS) {
|
|
7355
7400
|
evictLRU();
|
|
7356
7401
|
}
|
|
7357
|
-
const dbPath =
|
|
7402
|
+
const dbPath = path23.join(SHARDS_DIR, `${safeName}.db`);
|
|
7358
7403
|
const client = createClient2({
|
|
7359
7404
|
url: `file:${dbPath}`,
|
|
7360
7405
|
encryptionKey: _encryptionKey
|
|
@@ -7365,13 +7410,13 @@ function getShardClient(projectName) {
|
|
|
7365
7410
|
}
|
|
7366
7411
|
function shardExists(projectName) {
|
|
7367
7412
|
const safeName = safeShardName(projectName);
|
|
7368
|
-
return
|
|
7413
|
+
return existsSync19(path23.join(SHARDS_DIR, `${safeName}.db`));
|
|
7369
7414
|
}
|
|
7370
7415
|
function safeShardName(projectName) {
|
|
7371
7416
|
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7372
7417
|
}
|
|
7373
7418
|
function listShards() {
|
|
7374
|
-
if (!
|
|
7419
|
+
if (!existsSync19(SHARDS_DIR)) return [];
|
|
7375
7420
|
return readdirSync5(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
7376
7421
|
}
|
|
7377
7422
|
async function auditShardHealth(options = {}) {
|
|
@@ -7383,8 +7428,8 @@ async function auditShardHealth(options = {}) {
|
|
|
7383
7428
|
const names = listShards();
|
|
7384
7429
|
const shards = [];
|
|
7385
7430
|
for (const name of names) {
|
|
7386
|
-
const dbPath =
|
|
7387
|
-
const stat =
|
|
7431
|
+
const dbPath = path23.join(SHARDS_DIR, `${name}.db`);
|
|
7432
|
+
const stat = statSync3(dbPath);
|
|
7388
7433
|
const item = {
|
|
7389
7434
|
name,
|
|
7390
7435
|
path: dbPath,
|
|
@@ -7418,8 +7463,8 @@ async function auditShardHealth(options = {}) {
|
|
|
7418
7463
|
_shards.delete(name);
|
|
7419
7464
|
_shardLastAccess.delete(name);
|
|
7420
7465
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7421
|
-
const archivedPath =
|
|
7422
|
-
|
|
7466
|
+
const archivedPath = path23.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
|
|
7467
|
+
renameSync5(dbPath, archivedPath);
|
|
7423
7468
|
item.archivedPath = archivedPath;
|
|
7424
7469
|
}
|
|
7425
7470
|
} finally {
|
|
@@ -7635,12 +7680,12 @@ async function getReadyShardClient(projectName) {
|
|
|
7635
7680
|
client.close();
|
|
7636
7681
|
_shards.delete(safeName);
|
|
7637
7682
|
_shardLastAccess.delete(safeName);
|
|
7638
|
-
const dbPath =
|
|
7639
|
-
if (
|
|
7640
|
-
const stat =
|
|
7683
|
+
const dbPath = path23.join(SHARDS_DIR, `${safeName}.db`);
|
|
7684
|
+
if (existsSync19(dbPath)) {
|
|
7685
|
+
const stat = statSync3(dbPath);
|
|
7641
7686
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7642
|
-
const archivedPath =
|
|
7643
|
-
|
|
7687
|
+
const archivedPath = path23.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
7688
|
+
renameSync5(dbPath, archivedPath);
|
|
7644
7689
|
process.stderr.write(
|
|
7645
7690
|
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
|
|
7646
7691
|
`
|
|
@@ -7707,7 +7752,7 @@ var init_shard_manager = __esm({
|
|
|
7707
7752
|
"src/lib/shard-manager.ts"() {
|
|
7708
7753
|
"use strict";
|
|
7709
7754
|
init_config();
|
|
7710
|
-
SHARDS_DIR =
|
|
7755
|
+
SHARDS_DIR = path23.join(EXE_AI_DIR, "shards");
|
|
7711
7756
|
SHARD_IDLE_MS = 5 * 60 * 1e3;
|
|
7712
7757
|
MAX_OPEN_SHARDS = 10;
|
|
7713
7758
|
EVICTION_INTERVAL_MS = 60 * 1e3;
|
|
@@ -7974,6 +8019,164 @@ ${p.content}`).join("\n\n");
|
|
|
7974
8019
|
}
|
|
7975
8020
|
});
|
|
7976
8021
|
|
|
8022
|
+
// src/lib/memory-cards.ts
|
|
8023
|
+
var memory_cards_exports = {};
|
|
8024
|
+
__export(memory_cards_exports, {
|
|
8025
|
+
extractMemoryCards: () => extractMemoryCards,
|
|
8026
|
+
insertMemoryCardsForBatch: () => insertMemoryCardsForBatch,
|
|
8027
|
+
searchMemoryCards: () => searchMemoryCards
|
|
8028
|
+
});
|
|
8029
|
+
import { createHash as createHash2 } from "crypto";
|
|
8030
|
+
function stableId(memoryId, type, content) {
|
|
8031
|
+
return createHash2("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
|
|
8032
|
+
}
|
|
8033
|
+
function cleanText(text) {
|
|
8034
|
+
return text.replace(/```[\s\S]*?```/g, " ").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
8035
|
+
}
|
|
8036
|
+
function splitSentences(text) {
|
|
8037
|
+
return cleanText(text).split(/(?<=[.!?])\s+|\n+/).map((s) => s.trim()).filter((s) => s.length >= 24 && s.length <= MAX_SENTENCE_CHARS);
|
|
8038
|
+
}
|
|
8039
|
+
function inferCardType(sentence, toolName) {
|
|
8040
|
+
const lower = sentence.toLowerCase();
|
|
8041
|
+
if (toolName === "store_decision" || /\b(decided|decision|adr|approved|rejected)\b/.test(lower)) return "decision";
|
|
8042
|
+
if (/\b(prefers|preference|likes|dislikes|wants|doesn't want|does not want)\b/.test(lower)) return "preference";
|
|
8043
|
+
if (/\b(changed|updated|replaced|now|no longer|instead|supersedes)\b/.test(lower)) return "belief_update";
|
|
8044
|
+
if (toolName && ["Read", "Write", "Edit", "Bash"].includes(toolName)) return "code";
|
|
8045
|
+
if (/\b(meeting|deadline|shipped|launched|completed|failed|blocked|assigned|created)\b/.test(lower)) return "event";
|
|
8046
|
+
return "fact";
|
|
8047
|
+
}
|
|
8048
|
+
function extractSubject(sentence, agentId) {
|
|
8049
|
+
const explicit = sentence.match(/\b([A-Z][a-zA-Z0-9_-]{2,}(?:\s+[A-Z][a-zA-Z0-9_-]{2,})?)\b/);
|
|
8050
|
+
return explicit?.[1] ?? agentId;
|
|
8051
|
+
}
|
|
8052
|
+
function predicateFor(type) {
|
|
8053
|
+
switch (type) {
|
|
8054
|
+
case "preference":
|
|
8055
|
+
return "prefers";
|
|
8056
|
+
case "belief_update":
|
|
8057
|
+
return "updated";
|
|
8058
|
+
case "decision":
|
|
8059
|
+
return "decided";
|
|
8060
|
+
case "event":
|
|
8061
|
+
return "happened";
|
|
8062
|
+
case "code":
|
|
8063
|
+
return "implemented";
|
|
8064
|
+
default:
|
|
8065
|
+
return "states";
|
|
8066
|
+
}
|
|
8067
|
+
}
|
|
8068
|
+
function extractMemoryCards(row) {
|
|
8069
|
+
const sentences = splitSentences(row.raw_text);
|
|
8070
|
+
const cards = [];
|
|
8071
|
+
for (const sentence of sentences) {
|
|
8072
|
+
const type = inferCardType(sentence, row.tool_name);
|
|
8073
|
+
const subject = extractSubject(sentence, row.agent_id);
|
|
8074
|
+
const content = sentence.length > MAX_SENTENCE_CHARS ? `${sentence.slice(0, MAX_SENTENCE_CHARS - 1)}\u2026` : sentence;
|
|
8075
|
+
cards.push({
|
|
8076
|
+
id: stableId(row.id, type, content),
|
|
8077
|
+
memory_id: row.id,
|
|
8078
|
+
agent_id: row.agent_id,
|
|
8079
|
+
session_id: row.session_id,
|
|
8080
|
+
project_name: row.project_name ?? null,
|
|
8081
|
+
timestamp: row.timestamp,
|
|
8082
|
+
card_type: type,
|
|
8083
|
+
subject,
|
|
8084
|
+
predicate: predicateFor(type),
|
|
8085
|
+
object: content,
|
|
8086
|
+
content,
|
|
8087
|
+
source_ref: row.id,
|
|
8088
|
+
confidence: type === "fact" ? 0.55 : 0.65
|
|
8089
|
+
});
|
|
8090
|
+
if (cards.length >= MAX_CARDS_PER_MEMORY) break;
|
|
8091
|
+
}
|
|
8092
|
+
return cards;
|
|
8093
|
+
}
|
|
8094
|
+
async function insertMemoryCardsForBatch(rows) {
|
|
8095
|
+
const cards = rows.flatMap(extractMemoryCards);
|
|
8096
|
+
if (cards.length === 0) return 0;
|
|
8097
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
8098
|
+
const client = getClient();
|
|
8099
|
+
const stmts = cards.map((card) => ({
|
|
8100
|
+
sql: `INSERT OR IGNORE INTO memory_cards
|
|
8101
|
+
(id, memory_id, agent_id, session_id, project_name, timestamp, card_type,
|
|
8102
|
+
subject, predicate, object, content, source_ref, confidence, active, created_at)
|
|
8103
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?)`,
|
|
8104
|
+
args: [
|
|
8105
|
+
card.id,
|
|
8106
|
+
card.memory_id,
|
|
8107
|
+
card.agent_id,
|
|
8108
|
+
card.session_id,
|
|
8109
|
+
card.project_name,
|
|
8110
|
+
card.timestamp,
|
|
8111
|
+
card.card_type,
|
|
8112
|
+
card.subject,
|
|
8113
|
+
card.predicate,
|
|
8114
|
+
card.object,
|
|
8115
|
+
card.content,
|
|
8116
|
+
card.source_ref,
|
|
8117
|
+
card.confidence,
|
|
8118
|
+
now
|
|
8119
|
+
]
|
|
8120
|
+
}));
|
|
8121
|
+
await client.batch(stmts, "write");
|
|
8122
|
+
return cards.length;
|
|
8123
|
+
}
|
|
8124
|
+
function buildMatchExpr(queryText) {
|
|
8125
|
+
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);
|
|
8126
|
+
if (terms.length === 0) return null;
|
|
8127
|
+
return terms.map((t) => `${t}*`).join(terms.length >= 3 ? " AND " : " OR ");
|
|
8128
|
+
}
|
|
8129
|
+
async function searchMemoryCards(queryText, agentId, options) {
|
|
8130
|
+
const limit = options?.limit ?? 10;
|
|
8131
|
+
const matchExpr = buildMatchExpr(queryText);
|
|
8132
|
+
if (!matchExpr) return [];
|
|
8133
|
+
let sql = `SELECT c.id, c.memory_id, c.agent_id, c.session_id, c.project_name,
|
|
8134
|
+
c.timestamp, c.card_type, c.content, c.source_ref, c.confidence
|
|
8135
|
+
FROM memory_cards c
|
|
8136
|
+
JOIN memory_cards_fts fts ON c.rowid = fts.rowid
|
|
8137
|
+
WHERE memory_cards_fts MATCH ?
|
|
8138
|
+
AND c.agent_id = ?
|
|
8139
|
+
AND COALESCE(c.active, 1) = 1`;
|
|
8140
|
+
const args = [matchExpr, agentId];
|
|
8141
|
+
if (options?.projectName) {
|
|
8142
|
+
sql += ` AND c.project_name = ?`;
|
|
8143
|
+
args.push(options.projectName);
|
|
8144
|
+
}
|
|
8145
|
+
if (options?.since) {
|
|
8146
|
+
sql += ` AND c.timestamp >= ?`;
|
|
8147
|
+
args.push(options.since);
|
|
8148
|
+
}
|
|
8149
|
+
sql += ` ORDER BY rank LIMIT ?`;
|
|
8150
|
+
args.push(limit);
|
|
8151
|
+
const result = await getClient().execute({ sql, args });
|
|
8152
|
+
return result.rows.map((row) => ({
|
|
8153
|
+
id: `card:${String(row.id)}`,
|
|
8154
|
+
agent_id: String(row.agent_id),
|
|
8155
|
+
agent_role: "memory_card",
|
|
8156
|
+
session_id: String(row.session_id),
|
|
8157
|
+
timestamp: String(row.timestamp),
|
|
8158
|
+
tool_name: `memory_card:${String(row.card_type)}`,
|
|
8159
|
+
project_name: row.project_name == null ? "" : String(row.project_name),
|
|
8160
|
+
has_error: false,
|
|
8161
|
+
raw_text: `[${String(row.card_type)}] ${String(row.content)}
|
|
8162
|
+
Source memory: ${String(row.source_ref ?? row.memory_id)}`,
|
|
8163
|
+
vector: [],
|
|
8164
|
+
importance: 6,
|
|
8165
|
+
status: "active",
|
|
8166
|
+
confidence: Number(row.confidence ?? 0.6),
|
|
8167
|
+
last_accessed: String(row.timestamp)
|
|
8168
|
+
}));
|
|
8169
|
+
}
|
|
8170
|
+
var MAX_CARDS_PER_MEMORY, MAX_SENTENCE_CHARS;
|
|
8171
|
+
var init_memory_cards = __esm({
|
|
8172
|
+
"src/lib/memory-cards.ts"() {
|
|
8173
|
+
"use strict";
|
|
8174
|
+
init_database();
|
|
8175
|
+
MAX_CARDS_PER_MEMORY = 6;
|
|
8176
|
+
MAX_SENTENCE_CHARS = 360;
|
|
8177
|
+
}
|
|
8178
|
+
});
|
|
8179
|
+
|
|
7977
8180
|
// src/lib/store.ts
|
|
7978
8181
|
var store_exports = {};
|
|
7979
8182
|
__export(store_exports, {
|
|
@@ -8312,6 +8515,11 @@ async function flushBatch() {
|
|
|
8312
8515
|
const globalClient = getClient();
|
|
8313
8516
|
const globalStmts = batch.map(buildStmt);
|
|
8314
8517
|
await globalClient.batch(globalStmts, "write");
|
|
8518
|
+
try {
|
|
8519
|
+
const { insertMemoryCardsForBatch: insertMemoryCardsForBatch2 } = await Promise.resolve().then(() => (init_memory_cards(), memory_cards_exports));
|
|
8520
|
+
await insertMemoryCardsForBatch2(batch);
|
|
8521
|
+
} catch {
|
|
8522
|
+
}
|
|
8315
8523
|
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
8316
8524
|
_pendingRecords.splice(0, batch.length);
|
|
8317
8525
|
try {
|
|
@@ -8659,78 +8867,6 @@ var init_fast_db_init = __esm({
|
|
|
8659
8867
|
}
|
|
8660
8868
|
});
|
|
8661
8869
|
|
|
8662
|
-
// src/lib/memory-queue.ts
|
|
8663
|
-
import { appendFileSync as appendFileSync2, readFileSync as readFileSync15, renameSync as renameSync5, unlinkSync as unlinkSync9, existsSync as existsSync19, statSync as statSync3 } from "fs";
|
|
8664
|
-
import path23 from "path";
|
|
8665
|
-
function enqueueMemory(entry) {
|
|
8666
|
-
appendFileSync2(QUEUE_PATH2, JSON.stringify(entry) + "\n");
|
|
8667
|
-
}
|
|
8668
|
-
var QUEUE_PATH2, PROCESSING_PATH, TTL_MS2;
|
|
8669
|
-
var init_memory_queue = __esm({
|
|
8670
|
-
"src/lib/memory-queue.ts"() {
|
|
8671
|
-
"use strict";
|
|
8672
|
-
init_config();
|
|
8673
|
-
QUEUE_PATH2 = path23.join(EXE_AI_DIR, "memory-queue.jsonl");
|
|
8674
|
-
PROCESSING_PATH = QUEUE_PATH2 + ".processing";
|
|
8675
|
-
TTL_MS2 = 24 * 60 * 60 * 1e3;
|
|
8676
|
-
}
|
|
8677
|
-
});
|
|
8678
|
-
|
|
8679
|
-
// src/lib/memory-queue-client.ts
|
|
8680
|
-
var memory_queue_client_exports = {};
|
|
8681
|
-
__export(memory_queue_client_exports, {
|
|
8682
|
-
batchWriteMemoryViaDaemon: () => batchWriteMemoryViaDaemon,
|
|
8683
|
-
writeMemoryViaDaemon: () => writeMemoryViaDaemon
|
|
8684
|
-
});
|
|
8685
|
-
async function writeMemoryViaDaemon(entry) {
|
|
8686
|
-
if (process.env.EXE_IS_DAEMON === "1") {
|
|
8687
|
-
enqueueMemory(entry);
|
|
8688
|
-
return false;
|
|
8689
|
-
}
|
|
8690
|
-
if (!isClientConnected()) {
|
|
8691
|
-
enqueueMemory(entry);
|
|
8692
|
-
return false;
|
|
8693
|
-
}
|
|
8694
|
-
try {
|
|
8695
|
-
const response = await sendDaemonRequest({
|
|
8696
|
-
type: "write-memory",
|
|
8697
|
-
entry
|
|
8698
|
-
});
|
|
8699
|
-
if (response.ok) return true;
|
|
8700
|
-
enqueueMemory(entry);
|
|
8701
|
-
return false;
|
|
8702
|
-
} catch {
|
|
8703
|
-
enqueueMemory(entry);
|
|
8704
|
-
return false;
|
|
8705
|
-
}
|
|
8706
|
-
}
|
|
8707
|
-
async function batchWriteMemoryViaDaemon(entries) {
|
|
8708
|
-
if (entries.length === 0) return 0;
|
|
8709
|
-
if (process.env.EXE_IS_DAEMON === "1" || !isClientConnected()) {
|
|
8710
|
-
for (const entry of entries) enqueueMemory(entry);
|
|
8711
|
-
return 0;
|
|
8712
|
-
}
|
|
8713
|
-
try {
|
|
8714
|
-
const response = await sendDaemonRequest({
|
|
8715
|
-
type: "batch-write-memory",
|
|
8716
|
-
entries
|
|
8717
|
-
});
|
|
8718
|
-
if (response.ok) return response.count ?? entries.length;
|
|
8719
|
-
for (const entry of entries) enqueueMemory(entry);
|
|
8720
|
-
return 0;
|
|
8721
|
-
} catch {
|
|
8722
|
-
for (const entry of entries) enqueueMemory(entry);
|
|
8723
|
-
return 0;
|
|
8724
|
-
}
|
|
8725
|
-
}
|
|
8726
|
-
var init_memory_queue_client = __esm({
|
|
8727
|
-
"src/lib/memory-queue-client.ts"() {
|
|
8728
|
-
"use strict";
|
|
8729
|
-
init_exe_daemon_client();
|
|
8730
|
-
init_memory_queue();
|
|
8731
|
-
}
|
|
8732
|
-
});
|
|
8733
|
-
|
|
8734
8870
|
// src/lib/git-staleness.ts
|
|
8735
8871
|
var git_staleness_exports = {};
|
|
8736
8872
|
__export(git_staleness_exports, {
|
|
@@ -9278,6 +9414,119 @@ function buildAutoCheckpoint(input2) {
|
|
|
9278
9414
|
};
|
|
9279
9415
|
}
|
|
9280
9416
|
|
|
9417
|
+
// src/lib/memory-queue-client.ts
|
|
9418
|
+
init_exe_daemon_client();
|
|
9419
|
+
|
|
9420
|
+
// src/lib/memory-queue.ts
|
|
9421
|
+
init_config();
|
|
9422
|
+
import { appendFileSync as appendFileSync2, readFileSync as readFileSync15, renameSync as renameSync4, unlinkSync as unlinkSync9, existsSync as existsSync17, statSync as statSync2 } from "fs";
|
|
9423
|
+
import path21 from "path";
|
|
9424
|
+
var QUEUE_PATH2 = path21.join(EXE_AI_DIR, "memory-queue.jsonl");
|
|
9425
|
+
var PROCESSING_PATH = QUEUE_PATH2 + ".processing";
|
|
9426
|
+
var TTL_MS2 = 24 * 60 * 60 * 1e3;
|
|
9427
|
+
function enqueueMemory(entry) {
|
|
9428
|
+
appendFileSync2(QUEUE_PATH2, JSON.stringify(entry) + "\n");
|
|
9429
|
+
}
|
|
9430
|
+
|
|
9431
|
+
// src/lib/memory-queue-client.ts
|
|
9432
|
+
async function writeMemoryViaDaemon(entry) {
|
|
9433
|
+
if (process.env.EXE_IS_DAEMON === "1") {
|
|
9434
|
+
enqueueMemory(entry);
|
|
9435
|
+
return false;
|
|
9436
|
+
}
|
|
9437
|
+
if (!isClientConnected()) {
|
|
9438
|
+
enqueueMemory(entry);
|
|
9439
|
+
return false;
|
|
9440
|
+
}
|
|
9441
|
+
try {
|
|
9442
|
+
const response = await sendDaemonRequest({
|
|
9443
|
+
type: "write-memory",
|
|
9444
|
+
entry
|
|
9445
|
+
});
|
|
9446
|
+
if (response.ok) return true;
|
|
9447
|
+
enqueueMemory(entry);
|
|
9448
|
+
return false;
|
|
9449
|
+
} catch {
|
|
9450
|
+
enqueueMemory(entry);
|
|
9451
|
+
return false;
|
|
9452
|
+
}
|
|
9453
|
+
}
|
|
9454
|
+
|
|
9455
|
+
// src/lib/checkpoint-orchestrator.ts
|
|
9456
|
+
function toolNameForReason(reason) {
|
|
9457
|
+
switch (reason) {
|
|
9458
|
+
case "periodic":
|
|
9459
|
+
return "auto-summary";
|
|
9460
|
+
case "session-end":
|
|
9461
|
+
return "SessionEnd";
|
|
9462
|
+
case "pre-compact":
|
|
9463
|
+
return "pre-compact-hook";
|
|
9464
|
+
case "capacity-signal":
|
|
9465
|
+
return "auto-checkpoint";
|
|
9466
|
+
}
|
|
9467
|
+
}
|
|
9468
|
+
function importanceForReason(reason, override) {
|
|
9469
|
+
if (override !== void 0) return override;
|
|
9470
|
+
switch (reason) {
|
|
9471
|
+
case "periodic":
|
|
9472
|
+
return 7;
|
|
9473
|
+
case "session-end":
|
|
9474
|
+
case "pre-compact":
|
|
9475
|
+
case "capacity-signal":
|
|
9476
|
+
return 8;
|
|
9477
|
+
}
|
|
9478
|
+
}
|
|
9479
|
+
function buildContinuityCheckpoint(input2) {
|
|
9480
|
+
const { checkpointText, decisionTexts } = buildAutoCheckpoint({
|
|
9481
|
+
agentId: input2.agentId,
|
|
9482
|
+
agentRole: input2.agentRole,
|
|
9483
|
+
sessionId: input2.sessionId,
|
|
9484
|
+
projectName: input2.projectName,
|
|
9485
|
+
reason: input2.reason,
|
|
9486
|
+
memories: input2.memories ?? [],
|
|
9487
|
+
tasks: input2.tasks ?? [],
|
|
9488
|
+
maxSamples: input2.maxSamples
|
|
9489
|
+
});
|
|
9490
|
+
const extra = input2.extraSections?.filter((section) => section.trim().length > 0) ?? [];
|
|
9491
|
+
return {
|
|
9492
|
+
checkpointText: extra.length > 0 ? `${checkpointText}
|
|
9493
|
+
|
|
9494
|
+
${extra.join("\n\n")}` : checkpointText,
|
|
9495
|
+
decisionTexts
|
|
9496
|
+
};
|
|
9497
|
+
}
|
|
9498
|
+
async function writeContinuityCheckpoint(input2) {
|
|
9499
|
+
const result = buildContinuityCheckpoint(input2);
|
|
9500
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
9501
|
+
await writeMemoryViaDaemon({
|
|
9502
|
+
raw_text: result.checkpointText,
|
|
9503
|
+
agent_id: input2.agentId,
|
|
9504
|
+
agent_role: input2.agentRole,
|
|
9505
|
+
session_id: input2.sessionId,
|
|
9506
|
+
tool_name: toolNameForReason(input2.reason),
|
|
9507
|
+
project_name: input2.projectName,
|
|
9508
|
+
timestamp: now,
|
|
9509
|
+
importance: importanceForReason(input2.reason, input2.importance),
|
|
9510
|
+
task_id: input2.taskId,
|
|
9511
|
+
memory_type: "checkpoint"
|
|
9512
|
+
});
|
|
9513
|
+
const decisionLimit = input2.reason === "periodic" ? 3 : 5;
|
|
9514
|
+
for (const decisionText of result.decisionTexts.slice(0, decisionLimit)) {
|
|
9515
|
+
await writeMemoryViaDaemon({
|
|
9516
|
+
raw_text: decisionText,
|
|
9517
|
+
agent_id: input2.agentId,
|
|
9518
|
+
agent_role: input2.agentRole,
|
|
9519
|
+
session_id: input2.sessionId,
|
|
9520
|
+
tool_name: "auto-decision",
|
|
9521
|
+
project_name: input2.projectName,
|
|
9522
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9523
|
+
importance: 8,
|
|
9524
|
+
memory_type: "decision"
|
|
9525
|
+
});
|
|
9526
|
+
}
|
|
9527
|
+
return result;
|
|
9528
|
+
}
|
|
9529
|
+
|
|
9281
9530
|
// src/adapters/claude/hooks/session-end.ts
|
|
9282
9531
|
if (!process.env.AGENT_ID) {
|
|
9283
9532
|
process.env.AGENT_ID = "default";
|
|
@@ -9327,7 +9576,7 @@ Orphaned tasks at session end: ${orphanResult.rows.map((r) => `"${String(r.title
|
|
|
9327
9576
|
ORDER BY priority ASC, updated_at DESC LIMIT 10`,
|
|
9328
9577
|
args: [agent.agentId, ...seScope.args]
|
|
9329
9578
|
});
|
|
9330
|
-
|
|
9579
|
+
await writeContinuityCheckpoint({
|
|
9331
9580
|
agentId: agent.agentId,
|
|
9332
9581
|
agentRole: agent.agentRole,
|
|
9333
9582
|
sessionId: data.session_id,
|
|
@@ -9335,35 +9584,9 @@ Orphaned tasks at session end: ${orphanResult.rows.map((r) => `"${String(r.title
|
|
|
9335
9584
|
reason: "session-end",
|
|
9336
9585
|
memories: recent.rows,
|
|
9337
9586
|
tasks: taskRows.rows,
|
|
9338
|
-
maxSamples: 12
|
|
9339
|
-
|
|
9340
|
-
const { writeMemoryViaDaemon: writeMemoryViaDaemon2 } = await Promise.resolve().then(() => (init_memory_queue_client(), memory_queue_client_exports));
|
|
9341
|
-
await writeMemoryViaDaemon2({
|
|
9342
|
-
raw_text: `${checkpointText}${orphanInfo ? `
|
|
9343
|
-
|
|
9344
|
-
## Session-End Warnings${orphanInfo}` : ""}`,
|
|
9345
|
-
agent_id: agent.agentId,
|
|
9346
|
-
agent_role: agent.agentRole,
|
|
9347
|
-
session_id: data.session_id,
|
|
9348
|
-
tool_name: "SessionEnd",
|
|
9349
|
-
project_name: projectName,
|
|
9350
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9351
|
-
importance: 8,
|
|
9352
|
-
memory_type: "checkpoint"
|
|
9587
|
+
maxSamples: 12,
|
|
9588
|
+
extraSections: orphanInfo ? [`## Session-End Warnings${orphanInfo}`] : []
|
|
9353
9589
|
});
|
|
9354
|
-
for (const decisionText of decisionTexts.slice(0, 5)) {
|
|
9355
|
-
await writeMemoryViaDaemon2({
|
|
9356
|
-
raw_text: decisionText,
|
|
9357
|
-
agent_id: agent.agentId,
|
|
9358
|
-
agent_role: agent.agentRole,
|
|
9359
|
-
session_id: data.session_id,
|
|
9360
|
-
tool_name: "auto-decision",
|
|
9361
|
-
project_name: projectName,
|
|
9362
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9363
|
-
importance: 8,
|
|
9364
|
-
memory_type: "decision"
|
|
9365
|
-
});
|
|
9366
|
-
}
|
|
9367
9590
|
try {
|
|
9368
9591
|
const { clearSessionFileReads: clearSessionFileReads2 } = await Promise.resolve().then(() => (init_git_staleness(), git_staleness_exports));
|
|
9369
9592
|
await clearSessionFileReads2(data.session_id);
|